Some fixes (DAPI, mcchat)

This commit is contained in:
Norbi Peti 2018-04-08 02:39:05 +02:00
parent b31aea0c04
commit 68e99e0000
No known key found for this signature in database
GPG key ID: DBA4C4549A927E56
2 changed files with 538 additions and 550 deletions

View file

@ -44,389 +44,391 @@ import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
public class MCChatListener implements Listener, IListener<MessageReceivedEvent> { public class MCChatListener implements Listener, IListener<MessageReceivedEvent> {
private BukkitTask sendtask; private BukkitTask sendtask;
private LinkedBlockingQueue<TBMCChatEvent> sendevents = new LinkedBlockingQueue<>(); private LinkedBlockingQueue<TBMCChatEvent> sendevents = new LinkedBlockingQueue<>();
private Runnable sendrunnable;
@EventHandler // Minecraft @EventHandler // Minecraft
public void onMCChat(TBMCChatEvent ev) { public void onMCChat(TBMCChatEvent ev) {
if (ev.isCancelled()) if (ev.isCancelled())
return; return;
sendevents.add(ev); sendevents.add(ev);
if (sendtask != null) if (sendtask != null)
return; return;
sendtask = Bukkit.getScheduler().runTaskAsynchronously(DiscordPlugin.plugin, () -> { sendrunnable = () -> {
try { // Runs forever - Not good, but most plugins don't support reloading the server anyways try {
while (true) { TBMCChatEvent e;
TBMCChatEvent e; try {
try { e = sendevents.take(); // Wait until an element is available
e = sendevents.take(); // Wait until an element is available } catch (InterruptedException ex) {
} catch (InterruptedException ex) { sendtask.cancel();
sendtask.cancel(); sendtask = null;
return; return;
} }
final String authorPlayer = "[" + DPUtils.sanitizeString(e.getChannel().DisplayName) + "] " // final String authorPlayer = "[" + DPUtils.sanitizeString(e.getChannel().DisplayName) + "] " //
+ (e.getSender() instanceof DiscordSenderBase ? "[D]" : "") // + (e.getSender() instanceof DiscordSenderBase ? "[D]" : "") //
+ (DPUtils.sanitizeString(e.getSender() instanceof Player // + (DPUtils.sanitizeString(e.getSender() instanceof Player //
? ((Player) e.getSender()).getDisplayName() // ? ((Player) e.getSender()).getDisplayName() //
: e.getSender().getName())); : e.getSender().getName()));
final EmbedBuilder embed = new EmbedBuilder().withAuthorName(authorPlayer) final EmbedBuilder embed = new EmbedBuilder().withAuthorName(authorPlayer)
.withDescription(e.getMessage()).withColor(new Color(e.getChannel().color.getRed(), .withDescription(e.getMessage()).withColor(new Color(e.getChannel().color.getRed(),
e.getChannel().color.getGreen(), e.getChannel().color.getBlue())); e.getChannel().color.getGreen(), e.getChannel().color.getBlue()));
// embed.appendField("Channel", ((e.getSender() instanceof DiscordSenderBase ? "d|" : "") // embed.appendField("Channel", ((e.getSender() instanceof DiscordSenderBase ? "d|" : "")
// + DiscordPlugin.sanitizeString(e.getChannel().DisplayName)), false); // + DiscordPlugin.sanitizeString(e.getChannel().DisplayName)), false);
if (e.getSender() instanceof Player) if (e.getSender() instanceof Player)
DPUtils.embedWithHead( DPUtils.embedWithHead(
embed.withAuthorUrl("https://tbmcplugins.github.io/profile.html?type=minecraft&id=" embed.withAuthorUrl("https://tbmcplugins.github.io/profile.html?type=minecraft&id="
+ ((Player) e.getSender()).getUniqueId()), + ((Player) e.getSender()).getUniqueId()),
e.getSender().getName()); e.getSender().getName());
else if (e.getSender() instanceof DiscordSenderBase) else if (e.getSender() instanceof DiscordSenderBase)
embed.withAuthorIcon(((DiscordSenderBase) e.getSender()).getUser().getAvatarURL()) embed.withAuthorIcon(((DiscordSenderBase) e.getSender()).getUser().getAvatarURL())
.withAuthorUrl("https://tbmcplugins.github.io/profile.html?type=discord&id=" .withAuthorUrl("https://tbmcplugins.github.io/profile.html?type=discord&id="
+ ((DiscordSenderBase) e.getSender()).getUser().getStringID()); // TODO: Constant/method to get URLs like this + ((DiscordSenderBase) e.getSender()).getUser().getStringID()); // TODO: Constant/method to get URLs like this
// embed.withFooterText(e.getChannel().DisplayName); // embed.withFooterText(e.getChannel().DisplayName);
final long nanoTime = System.nanoTime(); final long nanoTime = System.nanoTime();
Consumer<LastMsgData> doit = lastmsgdata -> { Consumer<LastMsgData> doit = lastmsgdata -> {
final EmbedObject embedObject = embed.build(); final EmbedObject embedObject = embed.build();
if (lastmsgdata.message == null || lastmsgdata.message.isDeleted() if (lastmsgdata.message == null || lastmsgdata.message.isDeleted()
|| !authorPlayer.equals(lastmsgdata.message.getEmbeds().get(0).getAuthor().getName()) || !authorPlayer.equals(lastmsgdata.message.getEmbeds().get(0).getAuthor().getName())
|| lastmsgdata.time / 1000000000f < nanoTime / 1000000000f - 120 || lastmsgdata.time / 1000000000f < nanoTime / 1000000000f - 120
|| !lastmsgdata.mcchannel.ID.equals(e.getChannel().ID)) { || !lastmsgdata.mcchannel.ID.equals(e.getChannel().ID)) {
lastmsgdata.message = DiscordPlugin.sendMessageToChannelWait(lastmsgdata.channel, "", lastmsgdata.message = DiscordPlugin.sendMessageToChannelWait(lastmsgdata.channel, "",
embedObject); // TODO Use ChromaBot API embedObject); // TODO Use ChromaBot API
lastmsgdata.time = nanoTime; lastmsgdata.time = nanoTime;
lastmsgdata.mcchannel = e.getChannel(); lastmsgdata.mcchannel = e.getChannel();
lastmsgdata.content = embedObject.description; lastmsgdata.content = embedObject.description;
} else } else
try { try {
lastmsgdata.content = embedObject.description = lastmsgdata.content + "\n" lastmsgdata.content = embedObject.description = lastmsgdata.content + "\n"
+ embedObject.description;// The message object doesn't get updated + embedObject.description;// The message object doesn't get updated
final LastMsgData _lastmsgdata = lastmsgdata; final LastMsgData _lastmsgdata = lastmsgdata;
DPUtils.perform(() -> _lastmsgdata.message.edit("", embedObject)); DPUtils.perform(() -> _lastmsgdata.message.edit("", embedObject));
} catch (MissingPermissionsException | DiscordException e1) { } catch (MissingPermissionsException | DiscordException e1) {
TBMCCoreAPI.SendException("An error occured while editing chat message!", e1); TBMCCoreAPI.SendException("An error occured while editing chat message!", e1);
} }
}; };
// Checks if the given channel is different than where the message was sent from // Checks if the given channel is different than where the message was sent from
Predicate<IChannel> isdifferentchannel = ch -> !(e.getSender() instanceof DiscordSenderBase) Predicate<IChannel> isdifferentchannel = ch -> !(e.getSender() instanceof DiscordSenderBase)
|| ((DiscordSenderBase) e.getSender()).getChannel().getLongID() != ch.getLongID(); || ((DiscordSenderBase) e.getSender()).getChannel().getLongID() != ch.getLongID();
if ((e.getChannel() == Channel.GlobalChat || e.getChannel().ID.equals("rp")) if ((e.getChannel() == Channel.GlobalChat || e.getChannel().ID.equals("rp"))
&& isdifferentchannel.test(DiscordPlugin.chatchannel)) && isdifferentchannel.test(DiscordPlugin.chatchannel))
doit.accept(lastmsgdata == null doit.accept(lastmsgdata == null
? lastmsgdata = new LastMsgData(DiscordPlugin.chatchannel, null, null) ? lastmsgdata = new LastMsgData(DiscordPlugin.chatchannel, null, null)
: lastmsgdata); : lastmsgdata);
for (LastMsgData data : lastmsgPerUser) { for (LastMsgData data : lastmsgPerUser) {
if (data.dp.isMinecraftChatEnabled() && isdifferentchannel.test(data.channel) if (data.dp.isMinecraftChatEnabled() && isdifferentchannel.test(data.channel)
&& e.shouldSendTo(getSender(data.channel, data.user, data.dp))) && e.shouldSendTo(getSender(data.channel, data.user, data.dp)))
doit.accept(data); doit.accept(data);
} }
} sendtask = Bukkit.getScheduler().runTaskAsynchronously(DiscordPlugin.plugin, sendrunnable);
} catch (Exception ex) { } catch (Exception ex) {
TBMCCoreAPI.SendException("Error while sending mesasge to Discord!", ex); TBMCCoreAPI.SendException("Error while sending mesasge to Discord!", ex);
} }
}); };
} sendtask = Bukkit.getScheduler().runTaskAsynchronously(DiscordPlugin.plugin, sendrunnable);
}
@RequiredArgsConstructor @RequiredArgsConstructor
private static class LastMsgData { private static class LastMsgData {
public IMessage message; public IMessage message;
public long time; public long time;
public String content; public String content;
public final IChannel channel; public final IChannel channel;
public Channel mcchannel; public Channel mcchannel;
public final IUser user; public final IUser user;
public final DiscordPlayer dp; public final DiscordPlayer dp;
} }
@EventHandler @EventHandler
public void onChatPreprocess(TBMCChatPreprocessEvent event) { public void onChatPreprocess(TBMCChatPreprocessEvent event) {
int start = -1; int start = -1;
while ((start = event.getMessage().indexOf('@', start + 1)) != -1) { while ((start = event.getMessage().indexOf('@', start + 1)) != -1) {
int mid = event.getMessage().indexOf('#', start + 1); int mid = event.getMessage().indexOf('#', start + 1);
if (mid == -1) if (mid == -1)
return; return;
int end_ = event.getMessage().indexOf(' ', mid + 1); int end_ = event.getMessage().indexOf(' ', mid + 1);
if (end_ == -1) if (end_ == -1)
end_ = event.getMessage().length(); end_ = event.getMessage().length();
final int end = end_; final int end = end_;
final int startF = start; final int startF = start;
DiscordPlugin.dc.getUsersByName(event.getMessage().substring(start + 1, mid)).stream() DiscordPlugin.dc.getUsersByName(event.getMessage().substring(start + 1, mid)).stream()
.filter(u -> u.getDiscriminator().equals(event.getMessage().substring(mid + 1, end))).findAny() .filter(u -> u.getDiscriminator().equals(event.getMessage().substring(mid + 1, end))).findAny()
.ifPresent(user -> event.setMessage(event.getMessage().substring(0, startF) + "@" + user.getName() .ifPresent(user -> event.setMessage(event.getMessage().substring(0, startF) + "@" + user.getName()
+ (event.getMessage().length() > end ? event.getMessage().substring(end) : ""))); // TODO: Add formatting + (event.getMessage().length() > end ? event.getMessage().substring(end) : ""))); // TODO: Add formatting
start = end; // Skip any @s inside the mention start = end; // Skip any @s inside the mention
} }
} }
private static final String[] UnconnectedCmds = new String[] { "list", "u", "shrug", "tableflip", "unflip", "mwiki", private static final String[] UnconnectedCmds = new String[]{"list", "u", "shrug", "tableflip", "unflip", "mwiki",
"yeehaw" }; "yeehaw"};
private static LastMsgData lastmsgdata; private static LastMsgData lastmsgdata;
private static short lastlist = 0; private static short lastlist = 0;
private static short lastlistp = 0; private static short lastlistp = 0;
/** /**
* Used for messages in PMs (mcchat). * Used for messages in PMs (mcchat).
*/ */
private static ArrayList<LastMsgData> lastmsgPerUser = new ArrayList<LastMsgData>(); private static ArrayList<LastMsgData> lastmsgPerUser = new ArrayList<LastMsgData>();
public static boolean privateMCChat(IChannel channel, boolean start, IUser user, DiscordPlayer dp) { public static boolean privateMCChat(IChannel channel, boolean start, IUser user, DiscordPlayer dp) {
TBMCPlayer mcp = dp.getAs(TBMCPlayer.class); TBMCPlayer mcp = dp.getAs(TBMCPlayer.class);
if (mcp != null) { // If the accounts aren't connected, can't make a connected sender if (mcp != null) { // If the accounts aren't connected, can't make a connected sender
val p = Bukkit.getPlayer(mcp.getUUID()); val p = Bukkit.getPlayer(mcp.getUUID());
val op = Bukkit.getOfflinePlayer(mcp.getUUID()); val op = Bukkit.getOfflinePlayer(mcp.getUUID());
if (start) { if (start) {
val sender = new DiscordConnectedPlayer(user, channel, mcp.getUUID(), op.getName()); val sender = new DiscordConnectedPlayer(user, channel, mcp.getUUID(), op.getName());
ConnectedSenders.put(user.getStringID(), sender); ConnectedSenders.put(user.getStringID(), sender);
if (p == null)// Player is offline - If the player is online, that takes precedence if (p == null)// Player is offline - If the player is online, that takes precedence
MCListener.callEventExcludingSome(new PlayerJoinEvent(sender, "")); MCListener.callEventExcludingSome(new PlayerJoinEvent(sender, ""));
} else { } else {
val sender = ConnectedSenders.remove(user.getStringID()); val sender = ConnectedSenders.remove(user.getStringID());
if (p == null)// Player is offline - If the player is online, that takes precedence if (p == null)// Player is offline - If the player is online, that takes precedence
MCListener.callEventExcludingSome(new PlayerQuitEvent(sender, "")); MCListener.callEventExcludingSome(new PlayerQuitEvent(sender, ""));
} }
} }
return start // return start //
? lastmsgPerUser.add(new LastMsgData(channel, user, dp)) // Doesn't support group DMs ? lastmsgPerUser.add(new LastMsgData(channel, user, dp)) // Doesn't support group DMs
: lastmsgPerUser.removeIf(lmd -> lmd.channel.getLongID() == channel.getLongID()); : lastmsgPerUser.removeIf(lmd -> lmd.channel.getLongID() == channel.getLongID());
} }
// ......................DiscordSender....DiscordConnectedPlayer.DiscordPlayerSender // ......................DiscordSender....DiscordConnectedPlayer.DiscordPlayerSender
// Offline public chat......x............................................ // Offline public chat......x............................................
// Online public chat.......x...........................................x // Online public chat.......x...........................................x
// Offline private chat.....x.......................x.................... // Offline private chat.....x.......................x....................
// Online private chat......x.......................x...................x // Online private chat......x.......................x...................x
// If online and enabling private chat, don't login // If online and enabling private chat, don't login
// If leaving the server and private chat is enabled (has ConnectedPlayer), call login in a task on lowest priority // If leaving the server and private chat is enabled (has ConnectedPlayer), call login in a task on lowest priority
// If private chat is enabled and joining the server, logout the fake player on highest priority // If private chat is enabled and joining the server, logout the fake player on highest priority
// If online and disabling private chat, don't logout // If online and disabling private chat, don't logout
// The maps may not contain the senders for UnconnectedSenders // The maps may not contain the senders for UnconnectedSenders
public static boolean isMinecraftChatEnabled(DiscordPlayer dp) { public static boolean isMinecraftChatEnabled(DiscordPlayer dp) {
return lastmsgPerUser.stream().anyMatch( return lastmsgPerUser.stream().anyMatch(
lmd -> ((IPrivateChannel) lmd.channel).getRecipient().getStringID().equals(dp.getDiscordID())); lmd -> ((IPrivateChannel) lmd.channel).getRecipient().getStringID().equals(dp.getDiscordID()));
} }
public static boolean isMinecraftChatEnabled(String did) { // Don't load the player data just for this public static boolean isMinecraftChatEnabled(String did) { // Don't load the player data just for this
return lastmsgPerUser.stream() return lastmsgPerUser.stream()
.anyMatch(lmd -> ((IPrivateChannel) lmd.channel).getRecipient().getStringID().equals(did)); .anyMatch(lmd -> ((IPrivateChannel) lmd.channel).getRecipient().getStringID().equals(did));
} }
/** /**
* May contain P&lt;DiscordID&gt; as key for public chat * May contain P&lt;DiscordID&gt; as key for public chat
*/ */
public static final HashMap<String, DiscordSender> UnconnectedSenders = new HashMap<>(); public static final HashMap<String, DiscordSender> UnconnectedSenders = new HashMap<>();
public static final HashMap<String, DiscordConnectedPlayer> ConnectedSenders = new HashMap<>(); public static final HashMap<String, DiscordConnectedPlayer> ConnectedSenders = new HashMap<>();
/** /**
* May contain P&lt;DiscordID&gt; as key for public chat * May contain P&lt;DiscordID&gt; as key for public chat
*/ */
public static final HashMap<String, DiscordPlayerSender> OnlineSenders = new HashMap<>(); public static final HashMap<String, DiscordPlayerSender> OnlineSenders = new HashMap<>();
public static short ListC = 0; public static short ListC = 0;
public static void resetLastMessage() { public static void resetLastMessage() {
(lastmsgdata == null ? lastmsgdata = new LastMsgData(DiscordPlugin.chatchannel, null, null) (lastmsgdata == null ? lastmsgdata = new LastMsgData(DiscordPlugin.chatchannel, null, null)
: lastmsgdata).message = null; : lastmsgdata).message = null;
} // Don't set the whole object to null, the player and channel information should be preserved } // Don't set the whole object to null, the player and channel information should be preserved
public static void resetLastMessage(IChannel channel) { public static void resetLastMessage(IChannel channel) {
for (LastMsgData data : lastmsgPerUser) for (LastMsgData data : lastmsgPerUser)
if (data.channel.getLongID() == channel.getLongID()) if (data.channel.getLongID() == channel.getLongID())
data.message = null; // Since only private channels are stored, only those will work anyways data.message = null; // Since only private channels are stored, only those will work anyways
} }
/** /**
* This overload sends it to the global chat. * This overload sends it to the global chat.
*/ */
public static void sendSystemMessageToChat(String msg) { public static void sendSystemMessageToChat(String msg) {
forAllMCChat(ch -> DiscordPlugin.sendMessageToChannel(ch, DPUtils.sanitizeString(msg))); forAllMCChat(ch -> DiscordPlugin.sendMessageToChannel(ch, DPUtils.sanitizeString(msg)));
} }
public static void sendSystemMessageToChat(TBMCSystemChatEvent event) { public static void sendSystemMessageToChat(TBMCSystemChatEvent event) {
forAllowedMCChat(ch -> DiscordPlugin.sendMessageToChannel(ch, DPUtils.sanitizeString(event.getMessage())), forAllowedMCChat(ch -> DiscordPlugin.sendMessageToChannel(ch, DPUtils.sanitizeString(event.getMessage())),
event); event);
} }
public static void forAllMCChat(Consumer<IChannel> action) { public static void forAllMCChat(Consumer<IChannel> action) {
action.accept(DiscordPlugin.chatchannel); action.accept(DiscordPlugin.chatchannel);
for (LastMsgData data : lastmsgPerUser) for (LastMsgData data : lastmsgPerUser)
action.accept(data.channel); action.accept(data.channel);
} }
private static void forAllowedMCChat(Consumer<IChannel> action, TBMCSystemChatEvent event) { private static void forAllowedMCChat(Consumer<IChannel> action, TBMCSystemChatEvent event) {
if (Channel.GlobalChat.ID.equals(event.getChannel().ID)) if (Channel.GlobalChat.ID.equals(event.getChannel().ID))
action.accept(DiscordPlugin.chatchannel); action.accept(DiscordPlugin.chatchannel);
for (LastMsgData data : lastmsgPerUser) for (LastMsgData data : lastmsgPerUser)
if (event.shouldSendTo(getSender(data.channel, data.user, data.dp))) if (event.shouldSendTo(getSender(data.channel, data.user, data.dp)))
action.accept(data.channel); action.accept(data.channel);
} }
private BukkitTask rectask; private BukkitTask rectask;
private LinkedBlockingQueue<MessageReceivedEvent> recevents = new LinkedBlockingQueue<>(); private LinkedBlockingQueue<MessageReceivedEvent> recevents = new LinkedBlockingQueue<>();
private IMessage lastmsgfromd; // Last message sent by a Discord user, used for clearing checkmarks private IMessage lastmsgfromd; // Last message sent by a Discord user, used for clearing checkmarks
@Override // Discord @Override // Discord
public void handle(MessageReceivedEvent ev) { public void handle(MessageReceivedEvent ev) {
if (DiscordPlugin.SafeMode) if (DiscordPlugin.SafeMode)
return; return;
val author = ev.getMessage().getAuthor(); val author = ev.getMessage().getAuthor();
if (!ev.getMessage().getChannel().getStringID().equals(DiscordPlugin.chatchannel.getStringID()) if (!ev.getMessage().getChannel().getStringID().equals(DiscordPlugin.chatchannel.getStringID())
&& !(ev.getMessage().getChannel().isPrivate() && isMinecraftChatEnabled(author.getStringID()))) && !(ev.getMessage().getChannel().isPrivate() && isMinecraftChatEnabled(author.getStringID())))
return; return;
if (author.isBot()) if (author.isBot())
return; return;
if (ev.getMessage().getContent().equalsIgnoreCase("mcchat")) if (ev.getMessage().getContent().equalsIgnoreCase("mcchat"))
return; // Race condition: If it gets here after it enabled mcchat it says it - I might as well allow disabling with this (CommandListener) return; // Race condition: If it gets here after it enabled mcchat it says it - I might as well allow disabling with this (CommandListener)
if (CommandListener.runCommand(ev.getMessage(), true)) if (CommandListener.runCommand(ev.getMessage(), true))
return; return;
if (!ev.getMessage().getChannel().isPrivate()) if (!ev.getMessage().getChannel().isPrivate())
resetLastMessage(); resetLastMessage();
else else
resetLastMessage(ev.getMessage().getChannel()); resetLastMessage(ev.getMessage().getChannel());
lastlist++; lastlist++;
recevents.add(ev); recevents.add(ev);
if (rectask != null) if (rectask != null)
return; return;
rectask = Bukkit.getScheduler().runTaskAsynchronously(DiscordPlugin.plugin, () -> { rectask = Bukkit.getScheduler().runTaskAsynchronously(DiscordPlugin.plugin, () -> {
while (true) { while (true) {
@val @val
sx.blah.discord.handle.impl.events.guild.channel.message.MessageReceivedEvent event; sx.blah.discord.handle.impl.events.guild.channel.message.MessageReceivedEvent event;
try { try {
event = recevents.take(); event = recevents.take();
} catch (InterruptedException e1) { } catch (InterruptedException e1) {
rectask.cancel(); rectask.cancel();
return; return;
} }
val sender = event.getMessage().getAuthor(); val sender = event.getMessage().getAuthor();
val user = DiscordPlayer.getUser(sender.getStringID(), DiscordPlayer.class); val user = DiscordPlayer.getUser(sender.getStringID(), DiscordPlayer.class);
String dmessage = event.getMessage().getContent(); String dmessage = event.getMessage().getContent();
try { try {
final DiscordSenderBase dsender = getSender(event.getMessage().getChannel(), sender, user); final DiscordSenderBase dsender = getSender(event.getMessage().getChannel(), sender, user);
for (IUser u : event.getMessage().getMentions()) { for (IUser u : event.getMessage().getMentions()) {
dmessage = dmessage.replace(u.mention(false), "@" + u.getName()); // TODO: IG Formatting dmessage = dmessage.replace(u.mention(false), "@" + u.getName()); // TODO: IG Formatting
final String nick = u.getNicknameForGuild(DiscordPlugin.mainServer); final String nick = u.getNicknameForGuild(DiscordPlugin.mainServer);
dmessage = dmessage.replace(u.mention(true), "@" + (nick != null ? nick : u.getName())); dmessage = dmessage.replace(u.mention(true), "@" + (nick != null ? nick : u.getName()));
} }
BiConsumer<Channel, String> sendChatMessage = (channel, msg) -> // BiConsumer<Channel, String> sendChatMessage = (channel, msg) -> //
TBMCChatAPI.SendChatMessage(channel, dsender, TBMCChatAPI.SendChatMessage(channel, dsender,
msg + (event.getMessage().getAttachments().size() > 0 ? "\n" + event.getMessage() msg + (event.getMessage().getAttachments().size() > 0 ? "\n" + event.getMessage()
.getAttachments().stream().map(a -> a.getUrl()).collect(Collectors.joining("\n")) .getAttachments().stream().map(a -> a.getUrl()).collect(Collectors.joining("\n"))
: "")); : ""));
boolean react = false; boolean react = false;
if (dmessage.startsWith("/")) { // Ingame command if (dmessage.startsWith("/")) { // Ingame command
DPUtils.perform(() -> { DPUtils.perform(() -> {
if (!event.getMessage().isDeleted() && !event.getChannel().isPrivate()) if (!event.getMessage().isDeleted() && !event.getChannel().isPrivate())
event.getMessage().delete(); event.getMessage().delete();
}); });
final String cmd = dmessage.substring(1).toLowerCase(); final String cmd = dmessage.substring(1).toLowerCase();
if (dsender instanceof DiscordSender && !Arrays.stream(UnconnectedCmds) if (dsender instanceof DiscordSender && !Arrays.stream(UnconnectedCmds)
.anyMatch(s -> cmd.equals(s) || cmd.startsWith(s + " "))) { .anyMatch(s -> cmd.equals(s) || cmd.startsWith(s + " "))) {
// Command not whitelisted // Command not whitelisted
dsender.sendMessage("Sorry, you can only access these commands:\n" dsender.sendMessage("Sorry, you can only access these commands:\n"
+ Arrays.stream(UnconnectedCmds).map(uc -> "/" + uc) + Arrays.stream(UnconnectedCmds).map(uc -> "/" + uc)
.collect(Collectors.joining(", ")) .collect(Collectors.joining(", "))
+ (user.getConnectedID(TBMCPlayer.class) == null + (user.getConnectedID(TBMCPlayer.class) == null
? "\nTo access your commands, first please connect your accounts, using @ChromaBot connect in " ? "\nTo access your commands, first please connect your accounts, using @ChromaBot connect in "
+ DiscordPlugin.botchannel.mention() + DiscordPlugin.botchannel.mention()
+ "\nThen you can access all of your regular commands (even offline) in private chat: DM me `mcchat`!" + "\nThen you can access all of your regular commands (even offline) in private chat: DM me `mcchat`!"
: "\nYou can access all of your regular commands (even offline) in private chat: DM me `mcchat`!")); : "\nYou can access all of your regular commands (even offline) in private chat: DM me `mcchat`!"));
return; return;
} }
if (lastlist > 5) { if (lastlist > 5) {
ListC = 0; ListC = 0;
lastlist = 0; lastlist = 0;
} }
if (cmd.equals("list") && Bukkit.getOnlinePlayers().size() == lastlistp && ListC++ > 2) // Lowered already if (cmd.equals("list") && Bukkit.getOnlinePlayers().size() == lastlistp && ListC++ > 2) // Lowered already
{ {
dsender.sendMessage("Stop it. You know the answer."); dsender.sendMessage("Stop it. You know the answer.");
lastlist = 0; lastlist = 0;
} else { } else {
int spi = cmd.indexOf(' '); int spi = cmd.indexOf(' ');
final String topcmd = spi == -1 ? cmd : cmd.substring(0, spi); final String topcmd = spi == -1 ? cmd : cmd.substring(0, spi);
Optional<Channel> ch = Channel.getChannels().stream() Optional<Channel> ch = Channel.getChannels().stream()
.filter(c -> c.ID.equalsIgnoreCase(topcmd)).findAny(); .filter(c -> c.ID.equalsIgnoreCase(topcmd)).findAny();
if (!ch.isPresent()) if (!ch.isPresent())
Bukkit.getScheduler().runTask(DiscordPlugin.plugin, Bukkit.getScheduler().runTask(DiscordPlugin.plugin,
() -> VanillaCommandListener.runBukkitOrVanillaCommand(dsender, cmd)); () -> VanillaCommandListener.runBukkitOrVanillaCommand(dsender, cmd));
else { else {
Channel chc = ch.get(); Channel chc = ch.get();
if (!chc.ID.equals(Channel.GlobalChat.ID) if (!chc.ID.equals(Channel.GlobalChat.ID)
&& !event.getMessage().getChannel().isPrivate()) && !event.getMessage().getChannel().isPrivate())
dsender.sendMessage( dsender.sendMessage(
"You can only talk in global in the public chat. DM `mcchat` to enable private chat to talk in the other channels."); "You can only talk in global in the public chat. DM `mcchat` to enable private chat to talk in the other channels.");
else { else {
if (spi == -1) // Switch channels if (spi == -1) // Switch channels
{ {
val oldch = dsender.getMcchannel(); val oldch = dsender.getMcchannel();
if (oldch instanceof ChatRoom) if (oldch instanceof ChatRoom)
((ChatRoom) oldch).leaveRoom(dsender); ((ChatRoom) oldch).leaveRoom(dsender);
if (!oldch.ID.equals(chc.ID)) { if (!oldch.ID.equals(chc.ID)) {
dsender.setMcchannel(chc); dsender.setMcchannel(chc);
if (chc instanceof ChatRoom) if (chc instanceof ChatRoom)
((ChatRoom) chc).joinRoom(dsender); ((ChatRoom) chc).joinRoom(dsender);
} else } else
dsender.setMcchannel(Channel.GlobalChat); dsender.setMcchannel(Channel.GlobalChat);
dsender.sendMessage("You're now talking in: " dsender.sendMessage("You're now talking in: "
+ DPUtils.sanitizeString(dsender.getMcchannel().DisplayName)); + DPUtils.sanitizeString(dsender.getMcchannel().DisplayName));
} else { // Send single message } else { // Send single message
sendChatMessage.accept(chc, cmd.substring(spi + 1)); sendChatMessage.accept(chc, cmd.substring(spi + 1));
react = true; react = true;
} }
} }
} }
} }
lastlistp = (short) Bukkit.getOnlinePlayers().size(); lastlistp = (short) Bukkit.getOnlinePlayers().size();
} else {// Not a command } else {// Not a command
if (dmessage.length() == 0 && event.getMessage().getAttachments().size() == 0 if (dmessage.length() == 0 && event.getMessage().getAttachments().size() == 0
&& !event.getChannel().isPrivate()) && !event.getChannel().isPrivate())
TBMCChatAPI.SendSystemMessage(Channel.GlobalChat, 0, TBMCChatAPI.SendSystemMessage(Channel.GlobalChat, 0,
(dsender instanceof Player ? ((Player) dsender).getDisplayName() (dsender instanceof Player ? ((Player) dsender).getDisplayName()
: dsender.getName()) + " pinned a message on Discord."); : dsender.getName()) + " pinned a message on Discord.");
else { else {
sendChatMessage.accept(dsender.getMcchannel(), dmessage); sendChatMessage.accept(dsender.getMcchannel(), dmessage);
react = true; react = true;
} }
} }
if (react) { if (react) {
try { try {
/* /*
* System.out.println("Got message: " + m.getContent() + " with embeds: " + m.getEmbeds().stream().map(e -> e.getTitle() + " " + e.getDescription()) * System.out.println("Got message: " + m.getContent() + " with embeds: " + m.getEmbeds().stream().map(e -> e.getTitle() + " " + e.getDescription())
* .collect(Collectors.joining("\n"))); * .collect(Collectors.joining("\n")));
*/ */
if (lastmsgfromd != null) { if (lastmsgfromd != null) {
DPUtils.perform(() -> lastmsgfromd.removeReaction(DiscordPlugin.dc.getOurUser(), DPUtils.perform(() -> lastmsgfromd.removeReaction(DiscordPlugin.dc.getOurUser(),
DiscordPlugin.DELIVERED_REACTION)); // Remove it no matter what, we know it's there 99.99% of the time DiscordPlugin.DELIVERED_REACTION)); // Remove it no matter what, we know it's there 99.99% of the time
} }
} catch (Exception e) { } catch (Exception e) {
TBMCCoreAPI.SendException("An error occured while removing reactions from chat!", e); TBMCCoreAPI.SendException("An error occured while removing reactions from chat!", e);
} }
lastmsgfromd = event.getMessage(); lastmsgfromd = event.getMessage();
DPUtils.perform(() -> event.getMessage().addReaction(DiscordPlugin.DELIVERED_REACTION)); DPUtils.perform(() -> event.getMessage().addReaction(DiscordPlugin.DELIVERED_REACTION));
} }
} catch (Exception e) { } catch (Exception e) {
TBMCCoreAPI.SendException("An error occured while handling message \"" + dmessage + "\"!", e); TBMCCoreAPI.SendException("An error occured while handling message \"" + dmessage + "\"!", e);
return; return;
} }
} }
}); });
} }
/** /**
* This method will find the best sender to use: if the player is online, use that, if not but connected then use that etc. * 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, DiscordPlayer dp) { private static DiscordSenderBase getSender(IChannel channel, final IUser author, DiscordPlayer dp) {
val key = (channel.isPrivate() ? "" : "P") + author.getStringID(); val key = (channel.isPrivate() ? "" : "P") + author.getStringID();
return Stream.<Supplier<Optional<DiscordSenderBase>>>of( // https://stackoverflow.com/a/28833677/2703239 return Stream.<Supplier<Optional<DiscordSenderBase>>>of( // https://stackoverflow.com/a/28833677/2703239
() -> Optional.ofNullable(OnlineSenders.get(key)), // Find first non-null () -> Optional.ofNullable(OnlineSenders.get(key)), // Find first non-null
() -> Optional.ofNullable(ConnectedSenders.get(key)), // This doesn't support the public chat, but it'll always return null for it () -> Optional.ofNullable(ConnectedSenders.get(key)), // This doesn't support the public chat, but it'll always return null for it
() -> Optional.ofNullable(UnconnectedSenders.get(key)), () -> { () -> Optional.ofNullable(UnconnectedSenders.get(key)), () -> {
val dsender = new DiscordSender(author, channel); val dsender = new DiscordSender(author, channel);
UnconnectedSenders.put(key, dsender); UnconnectedSenders.put(key, dsender);
return Optional.of(dsender); return Optional.of(dsender);
}).map(Supplier::get).filter(Optional::isPresent).map(Optional::get).findFirst().get(); }).map(Supplier::get).filter(Optional::isPresent).map(Optional::get).findFirst().get();
} }
} }

View file

@ -1,15 +1,17 @@
package buttondevteam.discordplugin.listeners; package buttondevteam.discordplugin.listeners;
import java.util.Arrays; import buttondevteam.discordplugin.*;
import java.util.logging.Level; import buttondevteam.discordplugin.commands.ConnectCommand;
import buttondevteam.lib.TBMCCoreAPI;
import buttondevteam.lib.TBMCSystemChatEvent;
import buttondevteam.lib.player.*;
import com.earth2me.essentials.CommandSource;
import lombok.val;
import net.ess3.api.events.AfkStatusChangeEvent;
import net.ess3.api.events.MuteStatusChangeEvent;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.Event; import org.bukkit.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.entity.PlayerDeathEvent;
import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerKickEvent; import org.bukkit.event.player.PlayerKickEvent;
@ -21,211 +23,195 @@ import org.bukkit.event.server.ServerCommandEvent;
import org.bukkit.plugin.AuthorNagException; import org.bukkit.plugin.AuthorNagException;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.RegisteredListener; import org.bukkit.plugin.RegisteredListener;
import com.earth2me.essentials.CommandSource;
import buttondevteam.discordplugin.ChromaBot;
import buttondevteam.discordplugin.DPUtils;
import buttondevteam.discordplugin.DiscordConnectedPlayer;
import buttondevteam.discordplugin.DiscordPlayer;
import buttondevteam.discordplugin.DiscordPlayerSender;
import buttondevteam.discordplugin.DiscordPlugin;
import buttondevteam.discordplugin.commands.ConnectCommand;
import buttondevteam.lib.TBMCCoreAPI;
import buttondevteam.lib.TBMCSystemChatEvent;
import buttondevteam.lib.player.*;
import lombok.val;
import net.ess3.api.events.*;
import sx.blah.discord.handle.obj.IRole; import sx.blah.discord.handle.obj.IRole;
import sx.blah.discord.handle.obj.IUser; import sx.blah.discord.handle.obj.IUser;
import sx.blah.discord.util.DiscordException; import sx.blah.discord.util.DiscordException;
import sx.blah.discord.util.MissingPermissionsException; import sx.blah.discord.util.MissingPermissionsException;
import java.util.Arrays;
import java.util.logging.Level;
public class MCListener implements Listener { public class MCListener implements Listener {
@EventHandler(priority = EventPriority.HIGHEST) @EventHandler(priority = EventPriority.HIGHEST)
public void onPlayerLogin(PlayerLoginEvent e) { public void onPlayerLogin(PlayerLoginEvent e) {
if (e.getResult() != Result.ALLOWED) if (e.getResult() != Result.ALLOWED)
return; return;
MCChatListener.ConnectedSenders.values().stream() MCChatListener.ConnectedSenders.values().stream()
.filter(s -> s.getUniqueId().equals(e.getPlayer().getUniqueId())).findAny() .filter(s -> s.getUniqueId().equals(e.getPlayer().getUniqueId())).findAny()
.ifPresent(dcp -> callEventExcludingSome(new PlayerQuitEvent(dcp, ""))); .ifPresent(dcp -> callEventExcludingSome(new PlayerQuitEvent(dcp, "")));
} }
@EventHandler(priority = EventPriority.LOWEST) @EventHandler(priority = EventPriority.LOWEST)
public void onPlayerJoin(TBMCPlayerJoinEvent e) { public void onPlayerJoin(TBMCPlayerJoinEvent e) {
if (e.getPlayer() instanceof DiscordConnectedPlayer) if (e.getPlayer() instanceof DiscordConnectedPlayer)
return; // Don't show the joined message for the fake player return; // Don't show the joined message for the fake player
final Player p = e.getPlayer(); final Player p = e.getPlayer();
DiscordPlayer dp = e.GetPlayer().getAs(DiscordPlayer.class); DiscordPlayer dp = e.GetPlayer().getAs(DiscordPlayer.class);
if (dp != null) { if (dp != null) {
val user = DiscordPlugin.dc.getUserByID(Long.parseLong(dp.getDiscordID())); val user = DiscordPlugin.dc.getUserByID(Long.parseLong(dp.getDiscordID()));
MCChatListener.OnlineSenders.put(dp.getDiscordID(), MCChatListener.OnlineSenders.put(dp.getDiscordID(),
new DiscordPlayerSender(user, user.getOrCreatePMChannel(), p)); new DiscordPlayerSender(user, user.getOrCreatePMChannel(), p));
MCChatListener.OnlineSenders.put("P" + dp.getDiscordID(), MCChatListener.OnlineSenders.put("P" + dp.getDiscordID(),
new DiscordPlayerSender(user, DiscordPlugin.chatchannel, p)); new DiscordPlayerSender(user, DiscordPlugin.chatchannel, p));
} }
if (ConnectCommand.WaitingToConnect.containsKey(e.GetPlayer().PlayerName().get())) { if (ConnectCommand.WaitingToConnect.containsKey(e.GetPlayer().PlayerName().get())) {
IUser user = DiscordPlugin.dc IUser user = DiscordPlugin.dc
.getUserByID(Long.parseLong(ConnectCommand.WaitingToConnect.get(e.GetPlayer().PlayerName().get()))); .getUserByID(Long.parseLong(ConnectCommand.WaitingToConnect.get(e.GetPlayer().PlayerName().get())));
p.sendMessage("§bTo connect with the Discord account @" + user.getName() + "#" + user.getDiscriminator() p.sendMessage("§bTo connect with the Discord account @" + user.getName() + "#" + user.getDiscriminator()
+ " do /discord accept"); + " do /discord accept");
p.sendMessage("§bIf it wasn't you, do /discord decline"); p.sendMessage("§bIf it wasn't you, do /discord decline");
} }
if (!DiscordPlugin.hooked) if (!DiscordPlugin.hooked)
MCChatListener.sendSystemMessageToChat(e.GetPlayer().PlayerName().get() + " joined the game"); MCChatListener.sendSystemMessageToChat(e.GetPlayer().PlayerName().get() + " joined the game");
MCChatListener.ListC = 0; MCChatListener.ListC = 0;
ChromaBot.getInstance().updatePlayerList(); ChromaBot.getInstance().updatePlayerList();
} }
@EventHandler(priority = EventPriority.HIGHEST) @EventHandler(priority = EventPriority.HIGHEST)
public void onPlayerLeave(TBMCPlayerQuitEvent e) { public void onPlayerLeave(TBMCPlayerQuitEvent e) {
if (e.getPlayer() instanceof DiscordConnectedPlayer) if (e.getPlayer() instanceof DiscordConnectedPlayer)
return; // Only care about real users return; // Only care about real users
MCChatListener.OnlineSenders.entrySet() MCChatListener.OnlineSenders.entrySet()
.removeIf(entry -> entry.getValue().getUniqueId().equals(e.getPlayer().getUniqueId())); .removeIf(entry -> entry.getValue().getUniqueId().equals(e.getPlayer().getUniqueId()));
Bukkit.getScheduler().runTask(DiscordPlugin.plugin, Bukkit.getScheduler().runTask(DiscordPlugin.plugin,
() -> MCChatListener.ConnectedSenders.values().stream() () -> MCChatListener.ConnectedSenders.values().stream()
.filter(s -> s.getUniqueId().equals(e.getPlayer().getUniqueId())).findAny() .filter(s -> s.getUniqueId().equals(e.getPlayer().getUniqueId())).findAny()
.ifPresent(dcp -> callEventExcludingSome(new PlayerJoinEvent(dcp, "")))); .ifPresent(dcp -> callEventExcludingSome(new PlayerJoinEvent(dcp, ""))));
Bukkit.getScheduler().runTaskLaterAsynchronously(DiscordPlugin.plugin, Bukkit.getScheduler().runTaskLaterAsynchronously(DiscordPlugin.plugin,
ChromaBot.getInstance()::updatePlayerList, 5); ChromaBot.getInstance()::updatePlayerList, 5);
} }
@EventHandler(priority = EventPriority.HIGHEST) @EventHandler(priority = EventPriority.HIGHEST)
public void onPlayerKick(PlayerKickEvent e) { public void onPlayerKick(PlayerKickEvent e) {
if (!DiscordPlugin.hooked && !e.getReason().equals("The server is restarting") if (!DiscordPlugin.hooked && !e.getReason().equals("The server is restarting")
&& !e.getReason().equals("Server closed")) // The leave messages errored with the previous setup, I could make it wait since I moved it here, but instead I have a special && !e.getReason().equals("Server closed")) // The leave messages errored with the previous setup, I could make it wait since I moved it here, but instead I have a special
MCChatListener.sendSystemMessageToChat(e.getPlayer().getName() + " left the game"); // message for this - Oh wait this doesn't even send normally because of the hook MCChatListener.sendSystemMessageToChat(e.getPlayer().getName() + " left the game"); // message for this - Oh wait this doesn't even send normally because of the hook
} }
@EventHandler @EventHandler
public void onGetInfo(TBMCPlayerGetInfoEvent e) { public void onGetInfo(TBMCPlayerGetInfoEvent e) {
if (DiscordPlugin.SafeMode) if (DiscordPlugin.SafeMode)
return; return;
DiscordPlayer dp = e.getPlayer().getAs(DiscordPlayer.class); DiscordPlayer dp = e.getPlayer().getAs(DiscordPlayer.class);
if (dp == null || dp.getDiscordID() == null || dp.getDiscordID() == "") if (dp == null || dp.getDiscordID() == null || dp.getDiscordID() == "")
return; return;
IUser user = DiscordPlugin.dc.getUserByID(Long.parseLong(dp.getDiscordID())); IUser user = DiscordPlugin.dc.getUserByID(Long.parseLong(dp.getDiscordID()));
e.addInfo("Discord tag: " + user.getName() + "#" + user.getDiscriminator()); e.addInfo("Discord tag: " + user.getName() + "#" + user.getDiscriminator());
e.addInfo(user.getPresence().getStatus().toString()); e.addInfo(user.getPresence().getStatus().toString());
if (user.getPresence().getPlayingText().isPresent()) if (user.getPresence().getActivity().isPresent() && user.getPresence().getText().isPresent())
e.addInfo("Playing " + user.getPresence().getPlayingText().get()); e.addInfo(user.getPresence().getActivity().get() + ": " + user.getPresence().getText().get());
else if (user.getPresence().getStreamingUrl().isPresent()) }
e.addInfo("Streaming " + user.getPresence().getStreamingUrl().get());
}
@EventHandler(priority = EventPriority.LOW) @EventHandler(priority = EventPriority.LOW)
public void onPlayerDeath(PlayerDeathEvent e) { public void onPlayerDeath(PlayerDeathEvent e) {
if (!DiscordPlugin.hooked) if (!DiscordPlugin.hooked)
MCChatListener.sendSystemMessageToChat(e.getDeathMessage()); MCChatListener.sendSystemMessageToChat(e.getDeathMessage());
} }
@EventHandler @EventHandler
public void onPlayerAFK(AfkStatusChangeEvent e) { public void onPlayerAFK(AfkStatusChangeEvent e) {
if (e.isCancelled() || !e.getAffected().getBase().isOnline()) if (e.isCancelled() || !e.getAffected().getBase().isOnline())
return; return;
MCChatListener.sendSystemMessageToChat(DPUtils.sanitizeString(e.getAffected().getBase().getDisplayName()) MCChatListener.sendSystemMessageToChat(DPUtils.sanitizeString(e.getAffected().getBase().getDisplayName())
+ " is " + (e.getValue() ? "now" : "no longer") + " AFK."); + " is " + (e.getValue() ? "now" : "no longer") + " AFK.");
} }
@EventHandler @EventHandler
public void onServerCommand(ServerCommandEvent e) { public void onServerCommand(ServerCommandEvent e) {
DiscordPlugin.Restart = !e.getCommand().equalsIgnoreCase("stop"); // The variable is always true except if stopped DiscordPlugin.Restart = !e.getCommand().equalsIgnoreCase("stop"); // The variable is always true except if stopped
} }
@EventHandler @EventHandler
public void onPlayerMute(MuteStatusChangeEvent e) { public void onPlayerMute(MuteStatusChangeEvent e) {
try { try {
DPUtils.performNoWait(() -> { DPUtils.performNoWait(() -> {
final IRole role = DiscordPlugin.dc.getRoleByID(164090010461667328L); final IRole role = DiscordPlugin.dc.getRoleByID(164090010461667328L);
final CommandSource source = e.getAffected().getSource(); final CommandSource source = e.getAffected().getSource();
if (!source.isPlayer()) if (!source.isPlayer())
return; return;
final IUser user = DiscordPlugin.dc.getUserByID( final IUser user = DiscordPlugin.dc.getUserByID(
Long.parseLong(TBMCPlayerBase.getPlayer(source.getPlayer().getUniqueId(), TBMCPlayer.class) Long.parseLong(TBMCPlayerBase.getPlayer(source.getPlayer().getUniqueId(), TBMCPlayer.class)
.getAs(DiscordPlayer.class).getDiscordID())); // TODO: Use long .getAs(DiscordPlayer.class).getDiscordID())); // TODO: Use long
if (e.getValue()) if (e.getValue())
user.addRole(role); user.addRole(role);
else else
user.removeRole(role); user.removeRole(role);
}); });
} catch (DiscordException | MissingPermissionsException ex) { } catch (DiscordException | MissingPermissionsException ex) {
TBMCCoreAPI.SendException("Failed to give/take Muted role to player " + e.getAffected().getName() + "!", TBMCCoreAPI.SendException("Failed to give/take Muted role to player " + e.getAffected().getName() + "!",
ex); ex);
} }
} }
@EventHandler @EventHandler
public void onChatSystemMessage(TBMCSystemChatEvent event) { public void onChatSystemMessage(TBMCSystemChatEvent event) {
MCChatListener.sendSystemMessageToChat(event); MCChatListener.sendSystemMessageToChat(event);
} }
@EventHandler @EventHandler
public void onBroadcastMessage(BroadcastMessageEvent event) { public void onBroadcastMessage(BroadcastMessageEvent event) {
MCChatListener.sendSystemMessageToChat(event.getMessage()); MCChatListener.sendSystemMessageToChat(event.getMessage());
} }
private static final String[] EXCLUDED_PLUGINS = { "ProtocolLib", "LibsDisguises" }; private static final String[] EXCLUDED_PLUGINS = {"ProtocolLib", "LibsDisguises"};
public static void callEventExcludingSome(Event event) { public static void callEventExcludingSome(Event event) {
callEventExcluding(event, EXCLUDED_PLUGINS); callEventExcluding(event, EXCLUDED_PLUGINS);
} }
/** /**
* Calls an event with the given details. * Calls an event with the given details.
* <p> * <p>
* This method only synchronizes when the event is not asynchronous. * This method only synchronizes when the event is not asynchronous.
* *
* @param event * @param event Event details
* Event details * @param plugins The plugins to exclude. Not case sensitive.
* @param plugins */
* The plugins to exclude. Not case sensitive. private static void callEventExcluding(Event event, String... plugins) { // Copied from Spigot-API and modified a bit
*/ if (event.isAsynchronous()) {
private static void callEventExcluding(Event event, String... plugins) { // Copied from Spigot-API and modified a bit if (Thread.holdsLock(Bukkit.getPluginManager())) {
if (event.isAsynchronous()) { throw new IllegalStateException(
if (Thread.holdsLock(Bukkit.getPluginManager())) { event.getEventName() + " cannot be triggered asynchronously from inside synchronized code.");
throw new IllegalStateException( }
event.getEventName() + " cannot be triggered asynchronously from inside synchronized code."); if (Bukkit.getServer().isPrimaryThread()) {
} throw new IllegalStateException(
if (Bukkit.getServer().isPrimaryThread()) { event.getEventName() + " cannot be triggered asynchronously from primary server thread.");
throw new IllegalStateException( }
event.getEventName() + " cannot be triggered asynchronously from primary server thread."); fireEventExcluding(event, plugins);
} } else {
fireEventExcluding(event, plugins); synchronized (Bukkit.getPluginManager()) {
} else { fireEventExcluding(event, plugins);
synchronized (Bukkit.getPluginManager()) { }
fireEventExcluding(event, plugins); }
} }
}
}
private static void fireEventExcluding(Event event, String... plugins) { private static void fireEventExcluding(Event event, String... plugins) {
HandlerList handlers = event.getHandlers(); // Code taken from SimplePluginManager in Spigot-API HandlerList handlers = event.getHandlers(); // Code taken from SimplePluginManager in Spigot-API
RegisteredListener[] listeners = handlers.getRegisteredListeners(); RegisteredListener[] listeners = handlers.getRegisteredListeners();
val server = Bukkit.getServer(); val server = Bukkit.getServer();
for (RegisteredListener registration : listeners) { for (RegisteredListener registration : listeners) {
if (!registration.getPlugin().isEnabled() if (!registration.getPlugin().isEnabled()
|| Arrays.stream(plugins).anyMatch(p -> p.equalsIgnoreCase(registration.getPlugin().getName()))) || Arrays.stream(plugins).anyMatch(p -> p.equalsIgnoreCase(registration.getPlugin().getName())))
continue; // Modified to exclude plugins continue; // Modified to exclude plugins
try { try {
registration.callEvent(event); registration.callEvent(event);
} catch (AuthorNagException ex) { } catch (AuthorNagException ex) {
Plugin plugin = registration.getPlugin(); Plugin plugin = registration.getPlugin();
if (plugin.isNaggable()) { if (plugin.isNaggable()) {
plugin.setNaggable(false); plugin.setNaggable(false);
server.getLogger().log(Level.SEVERE, server.getLogger().log(Level.SEVERE,
String.format("Nag author(s): '%s' of '%s' about the following: %s", String.format("Nag author(s): '%s' of '%s' about the following: %s",
plugin.getDescription().getAuthors(), plugin.getDescription().getFullName(), plugin.getDescription().getAuthors(), plugin.getDescription().getFullName(),
ex.getMessage())); ex.getMessage()));
} }
} catch (Throwable ex) { } catch (Throwable ex) {
server.getLogger().log(Level.SEVERE, "Could not pass event " + event.getEventName() + " to " server.getLogger().log(Level.SEVERE, "Could not pass event " + event.getEventName() + " to "
+ registration.getPlugin().getDescription().getFullName(), ex); + registration.getPlugin().getDescription().getFullName(), ex);
} }
} }
} }
} }