Reorganized lots of stuff (components) #86

Merged
NorbiPeti merged 12 commits from dev into master 2019-01-03 20:39:53 +00:00
17 changed files with 402 additions and 343 deletions
Showing only changes of commit 1878a46041 - Show all commits

19
pom.xml
View file

@ -106,7 +106,9 @@
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<branch>master</branch> <!-- Should be master if building ButtonCore locally -->
<branch>
master
</branch> <!-- Should be master if building ButtonCore locally - the CI will overwrite it (see below) -->
</properties>
<repositories>
@ -160,11 +162,16 @@
<scope>provided</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.discord4j/Discord4J -->
<dependency>
<groupId>com.discord4j</groupId>
<artifactId>Discord4J</artifactId>
<version>2.10.1</version>
</dependency>
<!-- <dependency>
<groupId>com.discord4j</groupId>
<artifactId>Discord4J</artifactId>
<version>2.10.1</version>
</dependency> -->
<dependency>
<groupId>com.github.SizableShrimp</groupId>
<artifactId>Discord4J</artifactId>
<version>httprequestchange-SNAPSHOT</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-jdk14 -->
<dependency>
<groupId>org.slf4j</groupId>

View file

@ -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()));
}

View file

@ -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();
}
}

View file

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

View file

@ -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<ReadyEvent> {
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<ReadyEvent> {
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<ReadyEvent> {
@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<ReadyEvent> {
+ "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<ReadyEvent> {
.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<IMessage> r = () -> embed == null ? channel.sendMessage(content)
: channel.sendMessage(content, embed, false);

View file

@ -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);

View file

@ -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);

View file

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

View file

@ -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." //

View file

@ -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() {

View file

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

View file

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

View file

@ -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<MessageReceivedEvent> {
private BukkitTask sendtask;
@ -105,7 +95,7 @@ public class MCChatListener implements Listener, IListener<MessageReceivedEvent>
// embed.withFooterText(e.getChannel().DisplayName);
embed.withTimestamp(time);
final long nanoTime = System.nanoTime();
InterruptibleConsumer<LastMsgData> doit = lastmsgdata -> {
InterruptibleConsumer<MCChatUtils.LastMsgData> 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<MessageReceivedEvent>
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<MessageReceivedEvent>
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<MessageReceivedEvent>
}
}
@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<MessageReceivedEvent>
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<LastMsgData> lastmsgPerUser = new ArrayList<LastMsgData>();
/**
* Used for town or nation chats or anything else
*/
private static ArrayList<CustomLMD> lastmsgCustom = new ArrayList<>();
private static LongObjectHashMap<IMessage> 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 extends DiscordSenderBase> T addSender(HashMap<String, HashMap<IChannel, T>> senders,
IUser user, T sender) {
return addSender(senders, user.getStringID(), sender);
}
public static <T extends DiscordSenderBase> T addSender(HashMap<String, HashMap<IChannel, T>> 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 extends DiscordSenderBase> T getSender(HashMap<String, HashMap<IChannel, T>> senders,
IChannel channel, IUser user) {
var map = senders.get(user.getStringID());
if (map != null)
return map.get(channel);
return null;
}
public static <T extends DiscordSenderBase> T removeSender(HashMap<String, HashMap<IChannel, T>> 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<MessageReceivedEvent>
// 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<CustomLMD> getCustomChats() {
return Collections.unmodifiableList(lastmsgCustom);
}
/**
* May contain P&lt;DiscordID&gt; as key for public chat
*/
public static final HashMap<String, HashMap<IChannel, DiscordSender>> UnconnectedSenders = new HashMap<>();
public static final HashMap<String, HashMap<IChannel, DiscordConnectedPlayer>> ConnectedSenders = new HashMap<>();
/**
* May contain P&lt;DiscordID&gt; as key for public chat
*/
public static final HashMap<String, HashMap<IChannel, DiscordPlayerSender>> 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<IChannel> 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<IChannel> action, @Nullable ChannelconBroadcast toggle, boolean hookmsg) {
if (!GeneralEventBroadcasterModule.isHooked() || !hookmsg)
forAllMCChat(action);
final Consumer<CustomLMD> 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<IChannel> 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<IChannel> action, @Nullable CommandSender sender, @Nullable ChannelconBroadcast toggle, boolean hookmsg) {
if (!GeneralEventBroadcasterModule.isHooked() || !hookmsg)
forAllMCChat(action);
forAllowedCustomMCChat(action, sender, toggle);
}
public static Consumer<IChannel> send(String message) {
return ch -> DiscordPlugin.sendMessageToChannel(ch, DPUtils.sanitizeString(message));
}
public static void forAllowedMCChat(Consumer<IChannel> 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<MessageReceivedEvent>
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<MessageReceivedEvent>
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<MessageReceivedEvent>
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<MessageReceivedEvent>
.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<MessageReceivedEvent>
() -> { //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<MessageReceivedEvent>
}
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<MessageReceivedEvent>
} 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<MessageReceivedEvent>
}
}
/**
* 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.<Supplier<Optional<DiscordSenderBase>>>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<T> {
void accept(T value) throws TimeoutException, InterruptedException;

View file

@ -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<MCChatUtils.LastMsgData> 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));
}
}

View file

@ -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&lt;DiscordID&gt; as key for public chat
*/
public static final HashMap<String, HashMap<IChannel, DiscordSender>> UnconnectedSenders = new HashMap<>();
public static final HashMap<String, HashMap<IChannel, DiscordConnectedPlayer>> ConnectedSenders = new HashMap<>();
/**
* May contain P&lt;DiscordID&gt; as key for public chat
*/
public static final HashMap<String, HashMap<IChannel, DiscordPlayerSender>> OnlineSenders = new HashMap<>();
static LastMsgData lastmsgdata;
static LongObjectHashMap<IMessage> lastmsgfromd = new LongObjectHashMap<>(); // Last message sent by a Discord user, used for clearing checkmarks
public static <T extends DiscordSenderBase> T addSender(HashMap<String, HashMap<IChannel, T>> senders,
IUser user, T sender) {
return addSender(senders, user.getStringID(), sender);
}
public static <T extends DiscordSenderBase> T addSender(HashMap<String, HashMap<IChannel, T>> 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 extends DiscordSenderBase> T getSender(HashMap<String, HashMap<IChannel, T>> senders,
IChannel channel, IUser user) {
var map = senders.get(user.getStringID());
if (map != null)
return map.get(channel);
return null;
}
public static <T extends DiscordSenderBase> T removeSender(HashMap<String, HashMap<IChannel, T>> 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<IChannel> 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<IChannel> action, @Nullable ChannelconBroadcast toggle, boolean hookmsg) {
if (!GeneralEventBroadcasterModule.isHooked() || !hookmsg)
forAllMCChat(action);
final Consumer<MCChatCustom.CustomLMD> 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<IChannel> 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<IChannel> action, @Nullable CommandSender sender, @Nullable ChannelconBroadcast toggle, boolean hookmsg) {
if (!GeneralEventBroadcasterModule.isHooked() || !hookmsg)
forAllMCChat(action);
forAllowedCustomMCChat(action, sender, toggle);
}
public static Consumer<IChannel> send(String message) {
return ch -> DiscordPlugin.sendMessageToChannel(ch, DPUtils.sanitizeString(message));
}
public static void forAllowedMCChat(Consumer<IChannel> 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.<Supplier<Optional<DiscordSenderBase>>>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;
}
}

View file

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

View file

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