Refactoring & made mcchat teleport config

This commit is contained in:
Norbi Peti 2019-04-24 13:29:52 +02:00
parent 95af050517
commit 038cb98f1a
22 changed files with 488 additions and 445 deletions

View file

@ -1,10 +1,11 @@
package buttondevteam.discordplugin; package buttondevteam.discordplugin;
import buttondevteam.discordplugin.mcchat.MinecraftChatModule;
import buttondevteam.discordplugin.playerfaker.DiscordFakePlayer; import buttondevteam.discordplugin.playerfaker.DiscordFakePlayer;
import buttondevteam.discordplugin.playerfaker.VanillaCommandListener; import buttondevteam.discordplugin.playerfaker.VanillaCommandListener;
import discord4j.core.object.entity.MessageChannel;
import discord4j.core.object.entity.User;
import lombok.Getter; import lombok.Getter;
import sx.blah.discord.handle.obj.IUser;
import sx.blah.discord.handle.obj.MessageChannel;
import java.util.UUID; import java.util.UUID;
@ -12,8 +13,8 @@ public class DiscordConnectedPlayer extends DiscordFakePlayer implements IMCPlay
private static int nextEntityId = 10000; private static int nextEntityId = 10000;
private @Getter VanillaCommandListener<DiscordConnectedPlayer> vanillaCmdListener; private @Getter VanillaCommandListener<DiscordConnectedPlayer> vanillaCmdListener;
public DiscordConnectedPlayer(IUser user, MessageChannel channel, UUID uuid, String mcname) { public DiscordConnectedPlayer(User user, MessageChannel channel, UUID uuid, String mcname, MinecraftChatModule module) {
super(user, channel, nextEntityId++, uuid, mcname); super(user, channel, nextEntityId++, uuid, mcname ,module);
vanillaCmdListener = new VanillaCommandListener<>(this); vanillaCmdListener = new VanillaCommandListener<>(this);
} }

View file

@ -20,7 +20,7 @@ public class DiscordPlayer extends ChromaGamerBase {
/** /**
* Returns true if player has the private Minecraft chat enabled. For setting the value, see * Returns true if player has the private Minecraft chat enabled. For setting the value, see
* {@link MCChatPrivate#privateMCChat(sx.blah.discord.handle.obj.MessageChannel, boolean, sx.blah.discord.handle.obj.IUser, DiscordPlayer)} * {@link MCChatPrivate#privateMCChat(sx.blah.discord.handle.obj.MessageChannel, boolean, sx.blah.discord.handle.obj.User, DiscordPlayer)}
*/ */
public boolean isMinecraftChatEnabled() { public boolean isMinecraftChatEnabled() {
return MCChatPrivate.isMinecraftChatEnabled(this); return MCChatPrivate.isMinecraftChatEnabled(this);

View file

@ -1,6 +1,8 @@
package buttondevteam.discordplugin; package buttondevteam.discordplugin;
import buttondevteam.discordplugin.playerfaker.VanillaCommandListener; import buttondevteam.discordplugin.playerfaker.VanillaCommandListener;
import discord4j.core.object.entity.MessageChannel;
import discord4j.core.object.entity.User;
import lombok.Getter; import lombok.Getter;
import org.bukkit.*; import org.bukkit.*;
import org.bukkit.advancement.Advancement; import org.bukkit.advancement.Advancement;
@ -26,8 +28,6 @@ import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType; import org.bukkit.potion.PotionEffectType;
import org.bukkit.scoreboard.Scoreboard; import org.bukkit.scoreboard.Scoreboard;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
import sx.blah.discord.handle.obj.IUser;
import sx.blah.discord.handle.obj.MessageChannel;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.util.*; import java.util.*;
@ -38,7 +38,7 @@ public class DiscordPlayerSender extends DiscordSenderBase implements IMCPlayer<
protected Player player; protected Player player;
private @Getter VanillaCommandListener<DiscordPlayerSender> vanillaCmdListener; private @Getter VanillaCommandListener<DiscordPlayerSender> vanillaCmdListener;
public DiscordPlayerSender(IUser user, MessageChannel channel, Player player) { public DiscordPlayerSender(User user, MessageChannel channel, Player player) {
super(user, channel); super(user, channel);
this.player = player; this.player = player;
vanillaCmdListener = new VanillaCommandListener<DiscordPlayerSender>(this); vanillaCmdListener = new VanillaCommandListener<DiscordPlayerSender>(this);

View file

@ -8,7 +8,7 @@ import org.bukkit.permissions.Permission;
import org.bukkit.permissions.PermissionAttachment; import org.bukkit.permissions.PermissionAttachment;
import org.bukkit.permissions.PermissionAttachmentInfo; import org.bukkit.permissions.PermissionAttachmentInfo;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import sx.blah.discord.handle.obj.IUser; import sx.blah.discord.handle.obj.User;
import sx.blah.discord.handle.obj.MessageChannel; import sx.blah.discord.handle.obj.MessageChannel;
import java.util.Set; import java.util.Set;
@ -18,12 +18,12 @@ public class DiscordSender extends DiscordSenderBase implements CommandSender {
private String name; private String name;
public DiscordSender(IUser user, MessageChannel channel) { public DiscordSender(User user, MessageChannel channel) {
super(user, channel); super(user, channel);
name = user == null ? "Discord user" : user.getDisplayName(DiscordPlugin.mainServer); name = user == null ? "Discord user" : user.getDisplayName(DiscordPlugin.mainServer);
} }
public DiscordSender(IUser user, MessageChannel channel, String name) { public DiscordSender(User user, MessageChannel channel, String name) {
super(user, channel); super(user, channel);
this.name = name; this.name = name;
} }

View file

@ -1,20 +1,20 @@
package buttondevteam.discordplugin; package buttondevteam.discordplugin;
import buttondevteam.lib.TBMCCoreAPI; import buttondevteam.lib.TBMCCoreAPI;
import discord4j.core.object.entity.MessageChannel;
import discord4j.core.object.entity.User;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.scheduler.BukkitTask; import org.bukkit.scheduler.BukkitTask;
import sx.blah.discord.handle.obj.IUser;
import sx.blah.discord.handle.obj.MessageChannel;
public abstract class DiscordSenderBase implements CommandSender { public abstract class DiscordSenderBase implements CommandSender {
/** /**
* May be null. * May be null.
*/ */
protected IUser user; protected User user;
protected MessageChannel channel; protected MessageChannel channel;
protected DiscordSenderBase(IUser user, MessageChannel channel) { protected DiscordSenderBase(User user, MessageChannel channel) {
this.user = user; this.user = user;
this.channel = channel; this.channel = channel;
} }
@ -27,7 +27,7 @@ public abstract class DiscordSenderBase implements CommandSender {
* *
* @return The user or null. * @return The user or null.
*/ */
public IUser getUser() { public User getUser() {
return user; return user;
} }
@ -43,7 +43,7 @@ public abstract class DiscordSenderBase implements CommandSender {
* @return A Chroma user of Discord or a Discord user of Chroma * @return A Chroma user of Discord or a Discord user of Chroma
*/ */
public DiscordPlayer getChromaUser() { public DiscordPlayer getChromaUser() {
if (chromaUser == null) chromaUser = DiscordPlayer.getUser(user.getStringID(), DiscordPlayer.class); if (chromaUser == null) chromaUser = DiscordPlayer.getUser(user.getId().asString(), DiscordPlayer.class);
return chromaUser; return chromaUser;
} }
@ -58,8 +58,7 @@ public abstract class DiscordSenderBase implements CommandSender {
msgtosend += "\n" + sendmsg; msgtosend += "\n" + sendmsg;
if (sendtask == null) if (sendtask == null)
sendtask = Bukkit.getScheduler().runTaskLaterAsynchronously(DiscordPlugin.plugin, () -> { sendtask = Bukkit.getScheduler().runTaskLaterAsynchronously(DiscordPlugin.plugin, () -> {
DiscordPlugin.sendMessageToChannel(channel, channel.createMessage((!broadcast && user != null ? user.getMention() + "\n" : "") + msgtosend.trim());
(!broadcast && user != null ? user.mention() + "\n" : "") + msgtosend.trim());
sendtask = null; sendtask = null;
msgtosend = ""; msgtosend = "";
}, 4); // Waits a 0.2 second to gather all/most of the different messages }, 4); // Waits a 0.2 second to gather all/most of the different messages

View file

@ -28,10 +28,10 @@ public class ConnectCommand extends ICommand2DC {
@Command2.Subcommand @Command2.Subcommand
public boolean def(Command2DCSender sender, String Minecraftname) { public boolean def(Command2DCSender sender, String Minecraftname) {
val message = sender.getMessage(); val message = sender.getMessage();
if (WaitingToConnect.inverse().containsKey(message.getAuthor().getStringID())) { if (WaitingToConnect.inverse().containsKey(message.getAuthor().getId().asString())) {
DiscordPlugin.sendMessageToChannel(message.getChannel(), DiscordPlugin.sendMessageToChannel(message.getChannel(),
"Replacing " + WaitingToConnect.inverse().get(message.getAuthor().getStringID()) + " with " + Minecraftname); "Replacing " + WaitingToConnect.inverse().get(message.getAuthor().getId().asString()) + " with " + Minecraftname);
WaitingToConnect.inverse().remove(message.getAuthor().getStringID()); WaitingToConnect.inverse().remove(message.getAuthor().getId().asString());
} }
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
OfflinePlayer p = Bukkit.getOfflinePlayer(Minecraftname); OfflinePlayer p = Bukkit.getOfflinePlayer(Minecraftname);
@ -41,7 +41,7 @@ public class ConnectCommand extends ICommand2DC {
} }
try (TBMCPlayer pl = TBMCPlayerBase.getPlayer(p.getUniqueId(), TBMCPlayer.class)) { try (TBMCPlayer pl = TBMCPlayerBase.getPlayer(p.getUniqueId(), TBMCPlayer.class)) {
DiscordPlayer dp = pl.getAs(DiscordPlayer.class); DiscordPlayer dp = pl.getAs(DiscordPlayer.class);
if (dp != null && message.getAuthor().getStringID().equals(dp.getDiscordID())) { if (dp != null && message.getAuthor().getId().asString().equals(dp.getDiscordID())) {
DiscordPlugin.sendMessageToChannel(message.getChannel(), "You already have this account connected."); DiscordPlugin.sendMessageToChannel(message.getChannel(), "You already have this account connected.");
return true; return true;
} }
@ -49,7 +49,7 @@ public class ConnectCommand extends ICommand2DC {
TBMCCoreAPI.SendException("An error occured while connecting a Discord account!", e); TBMCCoreAPI.SendException("An error occured while connecting a Discord account!", e);
DiscordPlugin.sendMessageToChannel(message.getChannel(), "An internal error occured!\n" + e); DiscordPlugin.sendMessageToChannel(message.getChannel(), "An internal error occured!\n" + e);
} }
WaitingToConnect.put(p.getName(), message.getAuthor().getStringID()); WaitingToConnect.put(p.getName(), message.getAuthor().getId().asString());
DiscordPlugin.sendMessageToChannel(message.getChannel(), DiscordPlugin.sendMessageToChannel(message.getChannel(),
"Alright! Now accept the connection in Minecraft from the account " + Minecraftname "Alright! Now accept the connection in Minecraft from the account " + Minecraftname
+ " before the next server restart. You can also adjust the Minecraft name you want to connect to with the same command."); + " before the next server restart. You can also adjust the Minecraft name you want to connect to with the same command.");

View file

@ -8,7 +8,7 @@ import buttondevteam.lib.chat.CommandClass;
import buttondevteam.lib.player.ChromaGamerBase; import buttondevteam.lib.player.ChromaGamerBase;
import buttondevteam.lib.player.ChromaGamerBase.InfoTarget; import buttondevteam.lib.player.ChromaGamerBase.InfoTarget;
import lombok.val; import lombok.val;
import sx.blah.discord.handle.obj.IUser; import sx.blah.discord.handle.obj.User;
import sx.blah.discord.handle.obj.Message; import sx.blah.discord.handle.obj.Message;
import java.util.List; import java.util.List;
@ -24,23 +24,23 @@ public class UserinfoCommand extends ICommand2DC {
@Command2.Subcommand @Command2.Subcommand
public boolean def(Command2DCSender sender, @Command2.OptionalArg @Command2.TextArg String user) { public boolean def(Command2DCSender sender, @Command2.OptionalArg @Command2.TextArg String user) {
val message = sender.getMessage(); val message = sender.getMessage();
IUser target = null; User target = null;
if (user == null || user.length() == 0) if (user == null || user.length() == 0)
target = message.getAuthor(); target = message.getAuthor();
else { else {
final Optional<IUser> firstmention = message.getMentions().stream() final Optional<User> firstmention = message.getMentions().stream()
.filter(m -> !m.getStringID().equals(DiscordPlugin.dc.getOurUser().getStringID())).findFirst(); .filter(m -> !m.getId().asString().equals(DiscordPlugin.dc.getSelf().getId().asString())).findFirst();
if (firstmention.isPresent()) if (firstmention.isPresent())
target = firstmention.get(); target = firstmention.get();
else if (user.contains("#")) { else if (user.contains("#")) {
String[] targettag = user.split("#"); String[] targettag = user.split("#");
final List<IUser> targets = getUsers(message, targettag[0]); final List<User> targets = getUsers(message, targettag[0]);
if (targets.size() == 0) { if (targets.size() == 0) {
DiscordPlugin.sendMessageToChannel(message.getChannel(), DiscordPlugin.sendMessageToChannel(message.getChannel(),
"The user cannot be found (by name): " + user); "The user cannot be found (by name): " + user);
return true; return true;
} }
for (IUser ptarget : targets) { for (User ptarget : targets) {
if (ptarget.getDiscriminator().equalsIgnoreCase(targettag[1])) { if (ptarget.getDiscriminator().equalsIgnoreCase(targettag[1])) {
target = ptarget; target = ptarget;
break; break;
@ -53,7 +53,7 @@ public class UserinfoCommand extends ICommand2DC {
return true; return true;
} }
} else { } else {
final List<IUser> targets = getUsers(message, user); final List<User> targets = getUsers(message, user);
if (targets.size() == 0) { if (targets.size() == 0) {
DiscordPlugin.sendMessageToChannel(message.getChannel(), DiscordPlugin.sendMessageToChannel(message.getChannel(),
"The user cannot be found on Discord: " + user); "The user cannot be found on Discord: " + user);
@ -67,7 +67,7 @@ public class UserinfoCommand extends ICommand2DC {
target = targets.get(0); target = targets.get(0);
} }
} }
try (DiscordPlayer dp = ChromaGamerBase.getUser(target.getStringID(), DiscordPlayer.class)) { try (DiscordPlayer dp = ChromaGamerBase.getUser(target.getId().asString(), DiscordPlayer.class)) {
StringBuilder uinfo = new StringBuilder("User info for ").append(target.getName()).append(":\n"); StringBuilder uinfo = new StringBuilder("User info for ").append(target.getName()).append(":\n");
uinfo.append(dp.getInfo(InfoTarget.Discord)); uinfo.append(dp.getInfo(InfoTarget.Discord));
DiscordPlugin.sendMessageToChannel(message.getChannel(), uinfo.toString()); DiscordPlugin.sendMessageToChannel(message.getChannel(), uinfo.toString());
@ -78,8 +78,8 @@ public class UserinfoCommand extends ICommand2DC {
return true; return true;
} }
private List<IUser> getUsers(Message message, String args) { private List<User> getUsers(Message message, String args) {
final List<IUser> targets; final List<User> targets;
if (message.getChannel().isPrivate()) if (message.getChannel().isPrivate())
targets = DiscordPlugin.dc.getUsers().stream().filter(u -> u.getName().equalsIgnoreCase(args)) targets = DiscordPlugin.dc.getUsers().stream().filter(u -> u.getName().equalsIgnoreCase(args))
.collect(Collectors.toList()); .collect(Collectors.toList());

View file

@ -135,7 +135,7 @@ public class FunModule extends Component<DiscordPlugin> implements Listener {
if (event.getOldPresence().getStatus().equals(StatusType.OFFLINE) if (event.getOldPresence().getStatus().equals(StatusType.OFFLINE)
&& !event.getNewPresence().getStatus().equals(StatusType.OFFLINE) && !event.getNewPresence().getStatus().equals(StatusType.OFFLINE)
&& event.getUser().getRolesForGuild(channel.getGuild()).stream() && event.getUser().getRolesForGuild(channel.getGuild()).stream()
.anyMatch(r -> r.getLongID() == devrole.getLongID()) .anyMatch(r -> r.getId().asLong() == devrole.getId().asLong())
&& channel.getGuild().getUsersByRole(devrole).stream() && channel.getGuild().getUsersByRole(devrole).stream()
.noneMatch(u -> u.getPresence().getStatus().equals(StatusType.OFFLINE)) .noneMatch(u -> u.getPresence().getStatus().equals(StatusType.OFFLINE))
&& lasttime + 10 < TimeUnit.NANOSECONDS.toHours(System.nanoTime()) && lasttime + 10 < TimeUnit.NANOSECONDS.toHours(System.nanoTime())

View file

@ -3,6 +3,10 @@ package buttondevteam.discordplugin.listeners;
import buttondevteam.discordplugin.DiscordPlugin; import buttondevteam.discordplugin.DiscordPlugin;
import buttondevteam.discordplugin.commands.Command2DCSender; import buttondevteam.discordplugin.commands.Command2DCSender;
import buttondevteam.lib.TBMCCoreAPI; import buttondevteam.lib.TBMCCoreAPI;
import discord4j.core.object.entity.Message;
import discord4j.core.object.entity.MessageChannel;
import discord4j.core.object.entity.PrivateChannel;
import lombok.val;
import sx.blah.discord.handle.obj.IRole; import sx.blah.discord.handle.obj.IRole;
import sx.blah.discord.handle.obj.Message; import sx.blah.discord.handle.obj.Message;
import sx.blah.discord.handle.obj.MessageChannel; import sx.blah.discord.handle.obj.MessageChannel;
@ -16,22 +20,28 @@ public class CommandListener {
* @return Whether it ran the command * @return Whether it ran the command
*/ */
public static boolean runCommand(Message message, boolean mentionedonly) { public static boolean runCommand(Message message, boolean mentionedonly) {
if (message.getContent().length() == 0) if (message.getContent().isEmpty())
return false; //Pin messages and such, let the mcchat listener deal with it return false; //Pin messages and such, let the mcchat listener deal with it
final MessageChannel channel = message.getChannel(); final MessageChannel channel = message.getChannel().block();
@SuppressWarnings("OptionalGetWithoutIsPresent") val content = message.getContent().get();
if (channel == null) return false;
if (!mentionedonly) { //mentionedonly conditions are in CommonListeners if (!mentionedonly) { //mentionedonly conditions are in CommonListeners
if (!message.getChannel().isPrivate() if (!(channel instanceof PrivateChannel)
&& !(message.getContent().charAt(0) == DiscordPlugin.getPrefix() && !(content.charAt(0) == DiscordPlugin.getPrefix()
&& channel.getStringID().equals(DiscordPlugin.plugin.CommandChannel().get().getStringID()))) // && channel.getId().asString().equals(DiscordPlugin.plugin.CommandChannel().get().getId().asString()))) //
return false; return false;
message.getChannel().setTypingStatus(true); // Fun channel.type().subscribe(); // Fun
} }
final StringBuilder cmdwithargs = new StringBuilder(message.getContent()); final StringBuilder cmdwithargs = new StringBuilder(content);
final String mention = DiscordPlugin.dc.getOurUser().mention(false); val self=DiscordPlugin.dc.getSelf().block();
final String mentionNick = DiscordPlugin.dc.getOurUser().mention(true); if(self==null) return false;
val member=self.asMember(DiscordPlugin.mainServer.getId()).block();
if(member==null) return false;
final String mention = self.getMention();
final String mentionNick = member.getNicknameMention();
boolean gotmention = checkanddeletemention(cmdwithargs, mention, message); boolean gotmention = checkanddeletemention(cmdwithargs, mention, message);
gotmention = checkanddeletemention(cmdwithargs, mentionNick, message) || gotmention; gotmention = checkanddeletemention(cmdwithargs, mentionNick, message) || gotmention;
for (String mentionRole : (Iterable<String>) message.getRoleMentions().stream().filter(r -> DiscordPlugin.dc.getOurUser().hasRole(r)).map(IRole::mention)::iterator) for (String mentionRole : (Iterable<String>) message.getRoleMentions().filter(r -> member.getRoles().filter(r)).map(IRole::mention)::iterator) //TODO: Remove all that matches
gotmention = checkanddeletemention(cmdwithargs, mentionRole, message) || gotmention; // Delete all mentions gotmention = checkanddeletemention(cmdwithargs, mentionRole, message) || gotmention; // Delete all mentions
if (mentionedonly && !gotmention) { if (mentionedonly && !gotmention) {
message.getChannel().setTypingStatus(false); message.getChannel().setTypingStatus(false);

View file

@ -8,13 +8,13 @@ import buttondevteam.lib.player.TBMCPlayerJoinEvent;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener; import org.bukkit.event.Listener;
import org.bukkit.event.server.ServerCommandEvent; import org.bukkit.event.server.ServerCommandEvent;
import sx.blah.discord.handle.obj.IUser; import sx.blah.discord.handle.obj.User;
public class MCListener implements Listener { public class MCListener implements Listener {
@EventHandler @EventHandler
public void onPlayerJoin(TBMCPlayerJoinEvent e) { public void onPlayerJoin(TBMCPlayerJoinEvent e) {
if (ConnectCommand.WaitingToConnect.containsKey(e.GetPlayer().PlayerName().get())) { if (ConnectCommand.WaitingToConnect.containsKey(e.GetPlayer().PlayerName().get())) {
@SuppressWarnings("ConstantConditions") IUser user = DiscordPlugin.dc @SuppressWarnings("ConstantConditions") User user = DiscordPlugin.dc
.getUserByID(Long.parseLong(ConnectCommand.WaitingToConnect.get(e.GetPlayer().PlayerName().get()))); .getUserByID(Long.parseLong(ConnectCommand.WaitingToConnect.get(e.GetPlayer().PlayerName().get())));
e.getPlayer().sendMessage("§bTo connect with the Discord account @" + user.getName() + "#" + user.getDiscriminator() e.getPlayer().sendMessage("§bTo connect with the Discord account @" + user.getName() + "#" + user.getDiscriminator()
+ " do /discord accept"); + " do /discord accept");
@ -29,7 +29,7 @@ public class MCListener implements Listener {
DiscordPlayer dp = e.getPlayer().getAs(DiscordPlayer.class); DiscordPlayer dp = e.getPlayer().getAs(DiscordPlayer.class);
if (dp == null || dp.getDiscordID() == null || dp.getDiscordID().equals("")) if (dp == null || dp.getDiscordID() == null || dp.getDiscordID().equals(""))
return; return;
IUser user = DiscordPlugin.dc.getUserByID(Long.parseLong(dp.getDiscordID())); User 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().getActivity().isPresent() && user.getPresence().getText().isPresent()) if (user.getPresence().getActivity().isPresent() && user.getPresence().getText().isPresent())

View file

@ -95,7 +95,7 @@ public class ChannelconCommand extends ICommand2DC {
message.reply("MC channel with ID '" + channelID + "' not found! The ID is the command for it without the /."); message.reply("MC channel with ID '" + channelID + "' not found! The ID is the command for it without the /.");
return true; return true;
} }
val dp = DiscordPlayer.getUser(message.getAuthor().getStringID(), DiscordPlayer.class); val dp = DiscordPlayer.getUser(message.getAuthor().getId().asString(), DiscordPlayer.class);
val chp = dp.getAs(TBMCPlayer.class); val chp = dp.getAs(TBMCPlayer.class);
if (chp == null) { if (chp == null) {
message.reply("you need to connect your Minecraft account. On our server in " + DPUtils.botmention() + " do " + DiscordPlugin.getPrefix() + "connect <MCname>"); message.reply("you need to connect your Minecraft account. On our server in " + DPUtils.botmention() + " do " + DiscordPlugin.getPrefix() + "connect <MCname>");
@ -140,7 +140,7 @@ public class ChannelconCommand extends ICommand2DC {
"You need to have access to the MC channel and have manage permissions on the Discord channel.", // "You need to have access to the MC channel and have manage permissions on the Discord channel.", //
"You also need to have your Minecraft account connected. In " + DPUtils.botmention() + " use " + DiscordPlugin.getPrefix() + "connect <mcname>.", // "You also need to have your Minecraft account connected. In " + DPUtils.botmention() + " use " + DiscordPlugin.getPrefix() + "connect <mcname>.", //
"Call this command from the channel you want to use.", // "Call this command from the channel you want to use.", //
"Usage: @" + DiscordPlugin.dc.getOurUser().getName() + " channelcon <mcchannel>", // "Usage: @" + DiscordPlugin.dc.getSelf().getName() + " channelcon <mcchannel>", //
"Use the ID (command) of the channel, for example `g` for the global chat.", // "Use the ID (command) of the channel, for example `g` for the global chat.", //
"To remove a connection use @ChromaBot channelcon remove in the channel.", // "To remove a connection use @ChromaBot channelcon remove in the channel.", //
"Mentioning the bot is needed in this case because the " + DiscordPlugin.getPrefix() + " prefix only works in " + DPUtils.botmention() + ".", // "Mentioning the bot is needed in this case because the " + DiscordPlugin.getPrefix() + " prefix only works in " + DPUtils.botmention() + ".", //

View file

@ -24,7 +24,7 @@ public class MCChatCommand extends ICommand2DC {
message.reply("this command can only be issued in a direct message with the bot."); message.reply("this command can only be issued in a direct message with the bot.");
return true; return true;
} }
try (final DiscordPlayer user = DiscordPlayer.getUser(message.getAuthor().getStringID(), DiscordPlayer.class)) { try (final DiscordPlayer user = DiscordPlayer.getUser(message.getAuthor().getId().asString(), DiscordPlayer.class)) {
boolean mcchat = !user.isMinecraftChatEnabled(); boolean mcchat = !user.isMinecraftChatEnabled();
MCChatPrivate.privateMCChat(message.getChannel(), mcchat, message.getAuthor(), user); MCChatPrivate.privateMCChat(message.getChannel(), mcchat, message.getAuthor(), user);
message.reply("Minecraft chat " + (mcchat // message.reply("Minecraft chat " + (mcchat //

View file

@ -4,10 +4,12 @@ import buttondevteam.core.component.channel.Channel;
import buttondevteam.core.component.channel.ChatRoom; import buttondevteam.core.component.channel.ChatRoom;
import buttondevteam.discordplugin.DiscordConnectedPlayer; import buttondevteam.discordplugin.DiscordConnectedPlayer;
import buttondevteam.lib.TBMCSystemChatEvent; import buttondevteam.lib.TBMCSystemChatEvent;
import discord4j.core.object.entity.MessageChannel;
import discord4j.core.object.entity.TextChannel;
import discord4j.core.object.entity.User;
import discord4j.core.object.util.Snowflake;
import lombok.NonNull; import lombok.NonNull;
import lombok.val; import lombok.val;
import sx.blah.discord.handle.obj.IUser;
import sx.blah.discord.handle.obj.MessageChannel;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
@ -21,7 +23,7 @@ public class MCChatCustom {
*/ */
static ArrayList<CustomLMD> lastmsgCustom = new ArrayList<>(); static ArrayList<CustomLMD> lastmsgCustom = new ArrayList<>();
public static void addCustomChat(MessageChannel channel, String groupid, Channel mcchannel, IUser user, DiscordConnectedPlayer dcp, int toggles, Set<TBMCSystemChatEvent.BroadcastTarget> brtoggles) { public static void addCustomChat(MessageChannel channel, String groupid, Channel mcchannel, User user, DiscordConnectedPlayer dcp, int toggles, Set<TBMCSystemChatEvent.BroadcastTarget> brtoggles) {
if (mcchannel instanceof ChatRoom) { if (mcchannel instanceof ChatRoom) {
((ChatRoom) mcchannel).joinRoom(dcp); ((ChatRoom) mcchannel).joinRoom(dcp);
if (groupid == null) groupid = mcchannel.getGroupID(dcp); if (groupid == null) groupid = mcchannel.getGroupID(dcp);
@ -30,19 +32,19 @@ public class MCChatCustom {
lastmsgCustom.add(lmd); lastmsgCustom.add(lmd);
} }
public static boolean hasCustomChat(MessageChannel channel) { public static boolean hasCustomChat(Snowflake channel) {
return lastmsgCustom.stream().anyMatch(lmd -> lmd.channel.getLongID() == channel.getLongID()); return lastmsgCustom.stream().anyMatch(lmd -> lmd.channel.getId().asLong() == channel.asLong());
} }
@Nullable @Nullable
public static CustomLMD getCustomChat(MessageChannel channel) { public static CustomLMD getCustomChat(MessageChannel channel) {
return lastmsgCustom.stream().filter(lmd -> lmd.channel.getLongID() == channel.getLongID()).findAny().orElse(null); return lastmsgCustom.stream().filter(lmd -> lmd.channel.getId().asLong() == channel.getId().asLong()).findAny().orElse(null);
} }
public static boolean removeCustomChat(MessageChannel channel) { public static boolean removeCustomChat(MessageChannel channel) {
MCChatUtils.lastmsgfromd.remove(channel.getLongID()); MCChatUtils.lastmsgfromd.remove(channel.getId().asLong());
return lastmsgCustom.removeIf(lmd -> { return lastmsgCustom.removeIf(lmd -> {
if (lmd.channel.getLongID() != channel.getLongID()) if (lmd.channel.getId().asLong() != channel.getId().asLong())
return false; return false;
if (lmd.mcchannel instanceof ChatRoom) if (lmd.mcchannel instanceof ChatRoom)
((ChatRoom) lmd.mcchannel).leaveRoom(lmd.dcp); ((ChatRoom) lmd.mcchannel).leaveRoom(lmd.dcp);
@ -61,9 +63,9 @@ public class MCChatCustom {
public int toggles; public int toggles;
public Set<TBMCSystemChatEvent.BroadcastTarget> brtoggles; public Set<TBMCSystemChatEvent.BroadcastTarget> brtoggles;
private CustomLMD(@NonNull MessageChannel channel, @NonNull IUser user, private CustomLMD(@NonNull MessageChannel channel, @NonNull User user,
@NonNull String groupid, @NonNull Channel mcchannel, @NonNull DiscordConnectedPlayer dcp, int toggles, Set<TBMCSystemChatEvent.BroadcastTarget> brtoggles) { @NonNull String groupid, @NonNull Channel mcchannel, @NonNull DiscordConnectedPlayer dcp, int toggles, Set<TBMCSystemChatEvent.BroadcastTarget> brtoggles) {
super(channel, user); super((TextChannel) channel, user);
groupID = groupid; groupID = groupid;
this.mcchannel = mcchannel; this.mcchannel = mcchannel;
this.dcp = dcp; this.dcp = dcp;

View file

@ -14,6 +14,11 @@ import buttondevteam.lib.chat.ChatMessage;
import buttondevteam.lib.chat.TBMCChatAPI; import buttondevteam.lib.chat.TBMCChatAPI;
import buttondevteam.lib.player.TBMCPlayer; import buttondevteam.lib.player.TBMCPlayer;
import com.vdurmont.emoji.EmojiParser; import com.vdurmont.emoji.EmojiParser;
import discord4j.core.event.domain.message.MessageCreateEvent;
import discord4j.core.object.entity.MessageChannel;
import discord4j.core.object.entity.PrivateChannel;
import discord4j.core.object.entity.TextChannel;
import discord4j.core.spec.EmbedCreateSpec;
import lombok.val; import lombok.val;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -22,7 +27,7 @@ import org.bukkit.event.Listener;
import org.bukkit.scheduler.BukkitTask; import org.bukkit.scheduler.BukkitTask;
import sx.blah.discord.api.internal.json.objects.EmbedObject; 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.impl.events.guild.channel.message.MessageReceivedEvent;
import sx.blah.discord.handle.obj.IUser; import sx.blah.discord.handle.obj.User;
import sx.blah.discord.handle.obj.Message; import sx.blah.discord.handle.obj.Message;
import sx.blah.discord.handle.obj.MessageChannel; import sx.blah.discord.handle.obj.MessageChannel;
import sx.blah.discord.util.DiscordException; import sx.blah.discord.util.DiscordException;
@ -41,10 +46,10 @@ import java.util.function.Predicate;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class MCChatListener implements Listener { public class MCChatListener implements Listener {
private BukkitTask sendtask; private BukkitTask sendtask;
private LinkedBlockingQueue<AbstractMap.SimpleEntry<TBMCChatEvent, Instant>> sendevents = new LinkedBlockingQueue<>(); private LinkedBlockingQueue<AbstractMap.SimpleEntry<TBMCChatEvent, Instant>> sendevents = new LinkedBlockingQueue<>();
private Runnable sendrunnable; private Runnable sendrunnable;
private static Thread sendthread; private static Thread sendthread;
private final MinecraftChatModule module; private final MinecraftChatModule module;
public MCChatListener(MinecraftChatModule minecraftChatModule) { public MCChatListener(MinecraftChatModule minecraftChatModule) {
@ -52,359 +57,361 @@ public class MCChatListener implements Listener {
} }
@EventHandler // Minecraft @EventHandler // Minecraft
public void onMCChat(TBMCChatEvent ev) { public void onMCChat(TBMCChatEvent ev) {
if (!ComponentManager.isEnabled(MinecraftChatModule.class) || ev.isCancelled()) //SafeMode: Needed so it doesn't restart after server shutdown if (!ComponentManager.isEnabled(MinecraftChatModule.class) || ev.isCancelled()) //SafeMode: Needed so it doesn't restart after server shutdown
return; return;
sendevents.add(new AbstractMap.SimpleEntry<>(ev, Instant.now())); sendevents.add(new AbstractMap.SimpleEntry<>(ev, Instant.now()));
if (sendtask != null) if (sendtask != null)
return; return;
sendrunnable = () -> { sendrunnable = () -> {
sendthread = Thread.currentThread(); sendthread = Thread.currentThread();
processMCToDiscord(); processMCToDiscord();
if (DiscordPlugin.plugin.isEnabled()) //Don't run again if shutting down if (DiscordPlugin.plugin.isEnabled()) //Don't run again if shutting down
sendtask = Bukkit.getScheduler().runTaskAsynchronously(DiscordPlugin.plugin, sendrunnable); sendtask = Bukkit.getScheduler().runTaskAsynchronously(DiscordPlugin.plugin, sendrunnable);
}; };
sendtask = Bukkit.getScheduler().runTaskAsynchronously(DiscordPlugin.plugin, sendrunnable); sendtask = Bukkit.getScheduler().runTaskAsynchronously(DiscordPlugin.plugin, sendrunnable);
} }
private void processMCToDiscord() { private void processMCToDiscord() {
try { try {
TBMCChatEvent e; TBMCChatEvent e;
Instant time; Instant time;
val se = sendevents.take(); // Wait until an element is available val se = sendevents.take(); // Wait until an element is available
e = se.getKey(); e = se.getKey();
time = se.getValue(); time = se.getValue();
final String authorPlayer = "[" + DPUtils.sanitizeStringNoEscape(e.getChannel().DisplayName().get()) + "] " // final String authorPlayer = "[" + DPUtils.sanitizeStringNoEscape(e.getChannel().DisplayName().get()) + "] " //
+ ("Minecraft".equals(e.getOrigin()) ? "" : "[" + e.getOrigin().substring(0, 1) + "]") // + ("Minecraft".equals(e.getOrigin()) ? "" : "[" + e.getOrigin().substring(0, 1) + "]") //
+ (DPUtils.sanitizeStringNoEscape(e.getSender() instanceof Player // + (DPUtils.sanitizeStringNoEscape(e.getSender() instanceof Player //
? ((Player) e.getSender()).getDisplayName() // ? ((Player) e.getSender()).getDisplayName() //
: e.getSender().getName())); : e.getSender().getName()));
val color = e.getChannel().Color().get(); val color = e.getChannel().Color().get();
final EmbedBuilder embed = new EmbedBuilder().withAuthorName(authorPlayer) final EmbedCreateSpec embed = new EmbedBuilder().withAuthorName(authorPlayer)
.withDescription(e.getMessage()).withColor(new Color(color.getRed(), .withDescription(e.getMessage()).withColor(new Color(color.getRed(),
color.getGreen(), color.getBlue())); color.getGreen(), 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().getId().asString()); // TODO: Constant/method to get URLs like this
// embed.withFooterText(e.getChannel().DisplayName); // embed.withFooterText(e.getChannel().DisplayName);
embed.withTimestamp(time); embed.withTimestamp(time);
final long nanoTime = System.nanoTime(); final long nanoTime = System.nanoTime();
InterruptibleConsumer<MCChatUtils.LastMsgData> doit = lastmsgdata -> { InterruptibleConsumer<MCChatUtils.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 MCChatUtils.LastMsgData _lastmsgdata = lastmsgdata; lastmsgdata.message.edit(mes -> mes.setEmbed(ecs -> embedObject)).block();
DPUtils.perform(() -> _lastmsgdata.message.edit("", embedObject)); } catch (MissingPermissionsException | DiscordException e1) {
} catch (MissingPermissionsException | DiscordException e1) { TBMCCoreAPI.SendException("An error occurred while editing chat message!", e1);
TBMCCoreAPI.SendException("An error occurred 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 // Or if it was from MC
// Or if it was from MC
Predicate<MessageChannel> isdifferentchannel = ch -> !(e.getSender() instanceof DiscordSenderBase) Predicate<MessageChannel> isdifferentchannel = ch -> !(e.getSender() instanceof DiscordSenderBase)
|| ((DiscordSenderBase) e.getSender()).getChannel().getLongID() != ch.getLongID(); || ((DiscordSenderBase) e.getSender()).getChannel().getId().asLong() != ch.getId().asLong();
if (e.getChannel().isGlobal() if (e.getChannel().isGlobal()
&& (e.isFromCommand() || isdifferentchannel.test(module.chatChannel().get()))) && (e.isFromCommand() || isdifferentchannel.test(module.chatChannel().get())))
doit.accept(MCChatUtils.lastmsgdata == null doit.accept(MCChatUtils.lastmsgdata == null
? MCChatUtils.lastmsgdata = new MCChatUtils.LastMsgData(module.chatChannel().get(), null) ? MCChatUtils.lastmsgdata = new MCChatUtils.LastMsgData((TextChannel) module.chatChannel().get(), null)
: MCChatUtils.lastmsgdata); : MCChatUtils.lastmsgdata);
for (MCChatUtils.LastMsgData data : MCChatPrivate.lastmsgPerUser) { for (MCChatUtils.LastMsgData data : MCChatPrivate.lastmsgPerUser) {
if ((e.isFromCommand() || isdifferentchannel.test(data.channel)) if ((e.isFromCommand() || isdifferentchannel.test(data.channel))
&& e.shouldSendTo(MCChatUtils.getSender(data.channel, data.user))) && e.shouldSendTo(MCChatUtils.getSender(data.channel, data.user)))
doit.accept(data); doit.accept(data);
} }
val iterator = MCChatCustom.lastmsgCustom.iterator(); val iterator = MCChatCustom.lastmsgCustom.iterator();
while (iterator.hasNext()) { while (iterator.hasNext()) {
val lmd = iterator.next(); val lmd = iterator.next();
if ((e.isFromCommand() || isdifferentchannel.test(lmd.channel)) //Test if msg is from Discord if ((e.isFromCommand() || isdifferentchannel.test(lmd.channel)) //Test if msg is from Discord
&& e.getChannel().ID.equals(lmd.mcchannel.ID) //If it's from a command, the command msg has been deleted, so we need to send it && e.getChannel().ID.equals(lmd.mcchannel.ID) //If it's from a command, the command msg has been deleted, so we need to send it
&& e.getGroupID().equals(lmd.groupID)) { //Check if this is the group we want to test - #58 && e.getGroupID().equals(lmd.groupID)) { //Check if this is the group we want to test - #58
if (e.shouldSendTo(lmd.dcp)) //Check original user's permissions if (e.shouldSendTo(lmd.dcp)) //Check original user's permissions
doit.accept(lmd); doit.accept(lmd);
else { else {
iterator.remove(); //If the user no longer has permission, remove the connection iterator.remove(); //If the user no longer has permission, remove the connection
DiscordPlugin.sendMessageToChannel(lmd.channel, "The user no longer has permission to view the channel, connection removed."); DiscordPlugin.sendMessageToChannel(lmd.channel, "The user no longer has permission to view the channel, connection removed.");
} }
} }
} }
} catch (InterruptedException ex) { //Stop if interrupted anywhere } catch (InterruptedException ex) { //Stop if interrupted anywhere
sendtask.cancel(); sendtask.cancel();
sendtask = null; sendtask = null;
} catch (Exception ex) { } catch (Exception ex) {
TBMCCoreAPI.SendException("Error while sending message to Discord!", ex); TBMCCoreAPI.SendException("Error while sending message to Discord!", ex);
} }
} }
@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() val user = DiscordPlugin.dc.getUsers().filter(u -> u.getUsername().equals(event.getMessage().substring(startF + 1, mid)))
.filter(u -> u.getDiscriminator().equals(event.getMessage().substring(mid + 1, end))).findAny() .filter(u -> u.getDiscriminator().equals(event.getMessage().substring(mid + 1, end))).blockFirst();
.ifPresent(user -> event.setMessage(event.getMessage().substring(0, startF) + "@" + user.getName() if (user != null) //TODO: Nicknames
+ (event.getMessage().length() > end ? event.getMessage().substring(end) : ""))); // TODO: Add formatting event.setMessage(event.getMessage().substring(0, startF) + "@" + user.getUsername()
start = end; // Skip any @s inside the mention + (event.getMessage().length() > end ? event.getMessage().substring(end) : "")); // TODO: Add formatting
} start = end; // Skip any @s inside the mention
} }
}
// ......................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
/** /**
* Stop the listener. Any calls to onMCChat will restart it as long as we're not in safe mode. * Stop the listener. Any calls to onMCChat will restart it as long as we're not in safe mode.
* *
* @param wait Wait 5 seconds for the threads to stop * @param wait Wait 5 seconds for the threads to stop
*/ */
public static void stop(boolean wait) { public static void stop(boolean wait) {
if (sendthread != null) sendthread.interrupt(); if (sendthread != null) sendthread.interrupt();
if (recthread != null) recthread.interrupt(); if (recthread != null) recthread.interrupt();
try { try {
if (sendthread != null) { if (sendthread != null) {
sendthread.interrupt(); sendthread.interrupt();
if (wait) if (wait)
sendthread.join(5000); sendthread.join(5000);
} }
if (recthread != null) { if (recthread != null) {
recthread.interrupt(); recthread.interrupt();
if (wait) if (wait)
recthread.join(5000); recthread.join(5000);
} }
MCChatUtils.lastmsgdata = null; MCChatUtils.lastmsgdata = null;
MCChatPrivate.lastmsgPerUser.clear(); MCChatPrivate.lastmsgPerUser.clear();
MCChatCustom.lastmsgCustom.clear(); MCChatCustom.lastmsgCustom.clear();
MCChatUtils.lastmsgfromd.clear(); MCChatUtils.lastmsgfromd.clear();
MCChatUtils.ConnectedSenders.clear(); MCChatUtils.ConnectedSenders.clear();
MCChatUtils.UnconnectedSenders.clear(); MCChatUtils.UnconnectedSenders.clear();
recthread = sendthread = null; recthread = sendthread = null;
} catch (InterruptedException e) { } catch (InterruptedException e) {
e.printStackTrace(); //This thread shouldn't be interrupted e.printStackTrace(); //This thread shouldn't be interrupted
} }
} }
private BukkitTask rectask; private BukkitTask rectask;
private LinkedBlockingQueue<MessageReceivedEvent> recevents = new LinkedBlockingQueue<>(); private LinkedBlockingQueue<MessageCreateEvent> recevents = new LinkedBlockingQueue<>();
private Runnable recrun; private Runnable recrun;
private static Thread recthread; private static Thread recthread;
// Discord // Discord
public boolean handleDiscord(MessageReceivedEvent ev) { public boolean handleDiscord(MessageCreateEvent ev) {
if (!ComponentManager.isEnabled(MinecraftChatModule.class)) if (!ComponentManager.isEnabled(MinecraftChatModule.class))
return false; return false;
val author = ev.getMessage().getAuthor(); val author = ev.getMessage().getAuthor();
final boolean hasCustomChat = MCChatCustom.hasCustomChat(ev.getChannel()); final boolean hasCustomChat = MCChatCustom.hasCustomChat(ev.getMessage().getChannelId());
if (ev.getMessage().getChannel().getLongID() != module.chatChannel().get().getLongID() val channel = ev.getMessage().getChannel().block();
&& !(ev.getMessage().getChannel().isPrivate() && MCChatPrivate.isMinecraftChatEnabled(author.getStringID())) if (ev.getMessage().getChannelId().asLong() != module.chatChannel().get().getId().asLong()
&& !hasCustomChat) && !(channel instanceof PrivateChannel
&& author.map(u -> MCChatPrivate.isMinecraftChatEnabled(u.getId().asString())).orElse(false)
&& !hasCustomChat))
return false; //Chat isn't enabled on this channel return false; //Chat isn't enabled on this channel
if (ev.getMessage().getChannel().isPrivate() //Only in private chat if (channel instanceof PrivateChannel //Only in private chat
&& ev.getMessage().getContent().length() < "/mcchat<>".length() && ev.getMessage().getContent().isPresent()
&& ev.getMessage().getContent().replace("/", "") && ev.getMessage().getContent().get().length() < "/mcchat<>".length()
.equalsIgnoreCase("mcchat")) //Either mcchat or /mcchat && ev.getMessage().getContent().get().replace("/", "")
.equalsIgnoreCase("mcchat")) //Either mcchat or /mcchat
return false; //Allow disabling the chat if needed return false; //Allow disabling the chat if needed
if (CommandListener.runCommand(ev.getMessage(), true)) if (CommandListener.runCommand(ev.getMessage(), true))
return true; //Allow running commands in chat channels return true; //Allow running commands in chat channels
MCChatUtils.resetLastMessage(ev.getChannel()); MCChatUtils.resetLastMessage(channel);
recevents.add(ev); recevents.add(ev);
if (rectask != null) if (rectask != null)
return true; return true;
recrun = () -> { //Don't return in a while loop next time recrun = () -> { //Don't return in a while loop next time
recthread = Thread.currentThread(); recthread = Thread.currentThread();
processDiscordToMC(); processDiscordToMC();
if (DiscordPlugin.plugin.isEnabled()) //Don't run again if shutting down if (DiscordPlugin.plugin.isEnabled()) //Don't run again if shutting down
rectask = Bukkit.getScheduler().runTaskAsynchronously(DiscordPlugin.plugin, recrun); //Continue message processing rectask = Bukkit.getScheduler().runTaskAsynchronously(DiscordPlugin.plugin, recrun); //Continue message processing
}; };
rectask = Bukkit.getScheduler().runTaskAsynchronously(DiscordPlugin.plugin, recrun); //Start message processing rectask = Bukkit.getScheduler().runTaskAsynchronously(DiscordPlugin.plugin, recrun); //Start message processing
return true; return true;
} }
private void processDiscordToMC() { private void processDiscordToMC() {
@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();
String dmessage = event.getMessage().getContent(); String dmessage = event.getMessage().getContent();
try { try {
final DiscordSenderBase dsender = MCChatUtils.getSender(event.getMessage().getChannel(), sender); final DiscordSenderBase dsender = MCChatUtils.getSender(event.getMessage().getChannel(), sender);
val user = dsender.getChromaUser(); val user = dsender.getChromaUser();
for (IUser u : event.getMessage().getMentions()) { for (User 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()));
} }
for (MessageChannel ch : event.getMessage().getChannelMentions()) { for (MessageChannel ch : event.getMessage().getChannelMentions()) {
dmessage = dmessage.replace(ch.mention(), "#" + ch.getName()); // TODO: IG Formatting dmessage = dmessage.replace(ch.mention(), "#" + ch.getName()); // TODO: IG Formatting
} }
dmessage = EmojiParser.parseToAliases(dmessage, EmojiParser.FitzpatrickAction.PARSE); //Converts emoji to text- TODO: Add option to disable (resource pack?) dmessage = EmojiParser.parseToAliases(dmessage, EmojiParser.FitzpatrickAction.PARSE); //Converts emoji to text- TODO: Add option to disable (resource pack?)
dmessage = dmessage.replaceAll(":(\\S+)\\|type_(?:(\\d)|(1)_2):", ":$1::skin-tone-$2:"); //Convert to Discord's format so it still shows up dmessage = dmessage.replaceAll(":(\\S+)\\|type_(?:(\\d)|(1)_2):", ":$1::skin-tone-$2:"); //Convert to Discord's format so it still shows up
Function<String, String> getChatMessage = msg -> // Function<String, String> getChatMessage = msg -> //
msg + (event.getMessage().getAttachments().size() > 0 ? "\n" + event.getMessage() msg + (event.getMessage().getAttachments().size() > 0 ? "\n" + event.getMessage()
.getAttachments().stream().map(Message.Attachment::getUrl).collect(Collectors.joining("\n")) .getAttachments().stream().map(Message.Attachment::getUrl).collect(Collectors.joining("\n"))
: ""); : "");
MCChatCustom.CustomLMD clmd = MCChatCustom.getCustomChat(event.getChannel()); MCChatCustom.CustomLMD clmd = MCChatCustom.getCustomChat(event.getChannel());
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); final String cmd = dmessage.substring(1);
final String cmdlowercased = cmd.toLowerCase(); final String cmdlowercased = cmd.toLowerCase();
if (dsender instanceof DiscordSender && module.whitelistedCommands().get().stream() if (dsender instanceof DiscordSender && module.whitelistedCommands().get().stream()
.noneMatch(s -> cmdlowercased.equals(s) || cmdlowercased.startsWith(s + " "))) { .noneMatch(s -> cmdlowercased.equals(s) || cmdlowercased.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"
+ module.whitelistedCommands().get().stream().map(uc -> "/" + uc) + module.whitelistedCommands().get().stream().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 /connect in " ? "\nTo access your commands, first please connect your accounts, using /connect in "
+ DPUtils.botmention() + DPUtils.botmention()
+ "\nThen y" + "\nThen y"
: "\nY") : "\nY")
+ "ou can access all of your regular commands (even offline) in private chat: DM me `mcchat`!"); + "ou can access all of your regular commands (even offline) in private chat: DM me `mcchat`!");
return; return;
} }
val ev = new TBMCCommandPreprocessEvent(dsender, dmessage); val ev = new TBMCCommandPreprocessEvent(dsender, dmessage);
Bukkit.getPluginManager().callEvent(ev); Bukkit.getPluginManager().callEvent(ev);
if (ev.isCancelled()) if (ev.isCancelled())
return; return;
int spi = cmdlowercased.indexOf(' '); int spi = cmdlowercased.indexOf(' ');
final String topcmd = spi == -1 ? cmdlowercased : cmdlowercased.substring(0, spi); final String topcmd = spi == -1 ? cmdlowercased : cmdlowercased.substring(0, spi);
Optional<Channel> ch = Channel.getChannels() Optional<Channel> ch = Channel.getChannels()
.filter(c -> c.ID.equalsIgnoreCase(topcmd) .filter(c -> c.ID.equalsIgnoreCase(topcmd)
|| (c.IDs().get().length > 0 || (c.IDs().get().length > 0
&& Arrays.stream(c.IDs().get()).anyMatch(id -> id.equalsIgnoreCase(topcmd)))).findAny(); && Arrays.stream(c.IDs().get()).anyMatch(id -> id.equalsIgnoreCase(topcmd)))).findAny();
if (!ch.isPresent()) //TODO: What if talking in the public chat while we have it on a different one if (!ch.isPresent()) //TODO: What if talking in the public chat while we have it on a different one
Bukkit.getScheduler().runTask(DiscordPlugin.plugin, //Commands need to be run sync Bukkit.getScheduler().runTask(DiscordPlugin.plugin, //Commands need to be run sync
() -> { //TODO: Better handling... () -> { //TODO: Better handling...
val channel = user.channel(); val channel = user.channel();
val chtmp = channel.get(); val chtmp = channel.get();
if (clmd != null) { if (clmd != null) {
channel.set(clmd.mcchannel); //Hack to send command in the channel channel.set(clmd.mcchannel); //Hack to send command in the channel
} //TODO: Permcheck isn't implemented for commands } //TODO: Permcheck isn't implemented for commands
VanillaCommandListener.runBukkitOrVanillaCommand(dsender, cmd); VanillaCommandListener.runBukkitOrVanillaCommand(dsender, cmd);
Bukkit.getLogger().info(dsender.getName() + " issued command from Discord: /" + cmdlowercased); Bukkit.getLogger().info(dsender.getName() + " issued command from Discord: /" + cmdlowercased);
if (clmd != null) if (clmd != null)
channel.set(chtmp); channel.set(chtmp);
}); });
else { else {
Channel chc = ch.get(); Channel chc = ch.get();
if (!chc.isGlobal() && !event.getMessage().getChannel().isPrivate()) if (!chc.isGlobal() && !event.getMessage().getChannel().isPrivate())
dsender.sendMessage( dsender.sendMessage(
"You can only talk in a public chat here. DM `mcchat` to enable private chat to talk in the other channels."); "You can only talk in a public chat here. 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 channel = dsender.getChromaUser().channel(); val channel = dsender.getChromaUser().channel();
val oldch = channel.get(); val oldch = channel.get();
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)) {
channel.set(chc); channel.set(chc);
if (chc instanceof ChatRoom) if (chc instanceof ChatRoom)
((ChatRoom) chc).joinRoom(dsender); ((ChatRoom) chc).joinRoom(dsender);
} else } else
channel.set(Channel.GlobalChat); channel.set(Channel.GlobalChat);
dsender.sendMessage("You're now talking in: " dsender.sendMessage("You're now talking in: "
+ DPUtils.sanitizeString(channel.get().DisplayName().get())); + DPUtils.sanitizeString(channel.get().DisplayName().get()));
} else { // Send single message } else { // Send single message
final String msg = cmd.substring(spi + 1); final String msg = cmd.substring(spi + 1);
val cmb = ChatMessage.builder(dsender, user, getChatMessage.apply(msg)).fromCommand(true); val cmb = ChatMessage.builder(dsender, user, getChatMessage.apply(msg)).fromCommand(true);
if (clmd == null) if (clmd == null)
TBMCChatAPI.SendChatMessage(cmb.build(), chc); TBMCChatAPI.SendChatMessage(cmb.build(), chc);
else else
TBMCChatAPI.SendChatMessage(cmb.permCheck(clmd.dcp).build(), chc); TBMCChatAPI.SendChatMessage(cmb.permCheck(clmd.dcp).build(), chc);
react = true; react = true;
} }
} }
} }
} 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.getMessage().isSystemMessage()) { && !event.getChannel().isPrivate() && event.getMessage().isSystemMessage()) {
val rtr = clmd != null ? clmd.mcchannel.getRTR(clmd.dcp) val rtr = clmd != null ? clmd.mcchannel.getRTR(clmd.dcp)
: dsender.getChromaUser().channel().get().getRTR(dsender); : dsender.getChromaUser().channel().get().getRTR(dsender);
TBMCChatAPI.SendSystemMessage(clmd != null ? clmd.mcchannel : dsender.getChromaUser().channel().get(), rtr, TBMCChatAPI.SendSystemMessage(clmd != null ? clmd.mcchannel : dsender.getChromaUser().channel().get(), rtr,
(dsender instanceof Player ? ((Player) dsender).getDisplayName() (dsender instanceof Player ? ((Player) dsender).getDisplayName()
: dsender.getName()) + " pinned a message on Discord.", TBMCSystemChatEvent.BroadcastTarget.ALL); : dsender.getName()) + " pinned a message on Discord.", TBMCSystemChatEvent.BroadcastTarget.ALL);
} } else {
else { val cmb = ChatMessage.builder(dsender, user, getChatMessage.apply(dmessage)).fromCommand(false);
val cmb = ChatMessage.builder(dsender, user, getChatMessage.apply(dmessage)).fromCommand(false); if (clmd != null)
if (clmd != null) TBMCChatAPI.SendChatMessage(cmb.permCheck(clmd.dcp).build(), clmd.mcchannel);
TBMCChatAPI.SendChatMessage(cmb.permCheck(clmd.dcp).build(), clmd.mcchannel); else
else TBMCChatAPI.SendChatMessage(cmb.build());
TBMCChatAPI.SendChatMessage(cmb.build()); react = true;
react = true; }
} }
} if (react) {
if (react) { try {
try { val lmfd = MCChatUtils.lastmsgfromd.get(event.getChannel().getId().asLong());
val lmfd = MCChatUtils.lastmsgfromd.get(event.getChannel().getLongID()); if (lmfd != null) {
if (lmfd != null) { DPUtils.perform(() -> lmfd.removeReaction(DiscordPlugin.dc.getSelf(),
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
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); }
} MCChatUtils.lastmsgfromd.put(event.getChannel().getId().asLong(), event.getMessage());
MCChatUtils.lastmsgfromd.put(event.getChannel().getLongID(), 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); }
} }
}
@FunctionalInterface @FunctionalInterface
private interface InterruptibleConsumer<T> { private interface InterruptibleConsumer<T> {
void accept(T value) throws TimeoutException, InterruptedException; void accept(T value) throws TimeoutException, InterruptedException;
} }
} }

View file

@ -10,7 +10,7 @@ import org.bukkit.event.Event;
import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.event.player.PlayerQuitEvent;
import sx.blah.discord.handle.obj.IPrivateChannel; import sx.blah.discord.handle.obj.IPrivateChannel;
import sx.blah.discord.handle.obj.IUser; import sx.blah.discord.handle.obj.User;
import sx.blah.discord.handle.obj.MessageChannel; import sx.blah.discord.handle.obj.MessageChannel;
import java.util.ArrayList; import java.util.ArrayList;
@ -22,7 +22,7 @@ public class MCChatPrivate {
*/ */
static ArrayList<MCChatUtils.LastMsgData> lastmsgPerUser = new ArrayList<>(); static ArrayList<MCChatUtils.LastMsgData> lastmsgPerUser = new ArrayList<>();
public static boolean privateMCChat(MessageChannel channel, boolean start, IUser user, DiscordPlayer dp) { public static boolean privateMCChat(MessageChannel channel, boolean start, User 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());
@ -39,10 +39,10 @@ public class MCChatPrivate {
} }
} // ---- PermissionsEx warning is normal on logout ---- } // ---- PermissionsEx warning is normal on logout ----
if (!start) if (!start)
MCChatUtils.lastmsgfromd.remove(channel.getLongID()); MCChatUtils.lastmsgfromd.remove(channel.getId().asLong());
return start // return start //
? lastmsgPerUser.add(new MCChatUtils.LastMsgData(channel, user)) // Doesn't support group DMs ? lastmsgPerUser.add(new MCChatUtils.LastMsgData(channel, user)) // Doesn't support group DMs
: lastmsgPerUser.removeIf(lmd -> lmd.channel.getLongID() == channel.getLongID()); : lastmsgPerUser.removeIf(lmd -> lmd.channel.getId().asLong() == channel.getId().asLong());
} }
public static boolean isMinecraftChatEnabled(DiscordPlayer dp) { public static boolean isMinecraftChatEnabled(DiscordPlayer dp) {
@ -51,7 +51,7 @@ public class MCChatPrivate {
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().getId().asString().equals(did));
} }
public static void logoutAll() { public static void logoutAll() {

View file

@ -81,7 +81,7 @@ public class MCChatUtils {
return addSender(senders, user.getId().asLong(), sender); return addSender(senders, user.getId().asLong(), sender);
} }
public static <T extends DiscordSenderBase> T addSender(HashMap<Long, HashMap<Channel, T>> senders, public static <T extends DiscordSenderBase> T addSender(HashMap<Long, HashMap<MessageChannel, T>> senders,
long did, T sender) { long did, T sender) {
var map = senders.get(did); var map = senders.get(did);
if (map == null) if (map == null)
@ -91,8 +91,8 @@ public class MCChatUtils {
return sender; return sender;
} }
public static <T extends DiscordSenderBase> T getSender(HashMap<Long, HashMap<Channel, T>> senders, public static <T extends DiscordSenderBase> T getSender(HashMap<Long, HashMap<MessageChannel, T>> senders,
Channel channel, User user) { MessageChannel channel, User user) {
var map = senders.get(user.getId().asLong()); var map = senders.get(user.getId().asLong());
if (map != null) if (map != null)
return map.get(channel); return map.get(channel);
@ -172,7 +172,7 @@ public class MCChatUtils {
} }
public static void forAllowedMCChat(Consumer<MessageChannel> action, TBMCSystemChatEvent event) { public static void forAllowedMCChat(Consumer<MessageChannel> action, TBMCSystemChatEvent event) {
if (notEnabled()) return if (notEnabled()) return;
if (event.getChannel().isGlobal()) if (event.getChannel().isGlobal())
action.accept(module.chatChannel().get()); action.accept(module.chatChannel().get());
for (LastMsgData data : MCChatPrivate.lastmsgPerUser) for (LastMsgData data : MCChatPrivate.lastmsgPerUser)
@ -188,7 +188,7 @@ public class MCChatUtils {
/** /**
* 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.
*/ */
static DiscordSenderBase getSender(Channel channel, final User author) { static DiscordSenderBase getSender(MessageChannel channel, final User author) {
//noinspection OptionalGetWithoutIsPresent //noinspection OptionalGetWithoutIsPresent
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(getSender(OnlineSenders, channel, author)), // Find first non-null () -> Optional.ofNullable(getSender(OnlineSenders, channel, author)), // Find first non-null
@ -206,13 +206,13 @@ public class MCChatUtils {
*/ */
public static void resetLastMessage(Channel channel) { public static void resetLastMessage(Channel channel) {
if (notEnabled()) return; if (notEnabled()) return;
if (channel.getLongID() == module.chatChannel().get().getLongID()) { if (channel.getId().asLong() == module.chatChannel().get().getId().asLong()) {
(lastmsgdata == null ? lastmsgdata = new LastMsgData(module.chatChannel().get(), null) (lastmsgdata == null ? lastmsgdata = new LastMsgData(module.chatChannel().get(), null)
: lastmsgdata).message = null; : lastmsgdata).message = null;
return; return;
} // 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
for (LastMsgData data : channel.isPrivate() ? MCChatPrivate.lastmsgPerUser : MCChatCustom.lastmsgCustom) { for (LastMsgData data : channel.isPrivate() ? MCChatPrivate.lastmsgPerUser : MCChatCustom.lastmsgCustom) {
if (data.channel.getLongID() == channel.getLongID()) { if (data.channel.getId().asLong() == channel.getId().asLong()) {
data.message = null; data.message = null;
return; return;
} }

View file

@ -24,7 +24,7 @@ import org.bukkit.event.player.PlayerLoginEvent.Result;
import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.server.BroadcastMessageEvent; import org.bukkit.event.server.BroadcastMessageEvent;
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.User;
import sx.blah.discord.util.DiscordException; import sx.blah.discord.util.DiscordException;
import sx.blah.discord.util.MissingPermissionsException; import sx.blah.discord.util.MissingPermissionsException;
@ -115,7 +115,7 @@ class MCListener implements Listener {
final DiscordPlayer p = TBMCPlayerBase.getPlayer(source.getPlayer().getUniqueId(), TBMCPlayer.class) final DiscordPlayer p = TBMCPlayerBase.getPlayer(source.getPlayer().getUniqueId(), TBMCPlayer.class)
.getAs(DiscordPlayer.class); .getAs(DiscordPlayer.class);
if (p == null) return; if (p == null) return;
final IUser user = DiscordPlugin.dc.getUserByID( final User user = DiscordPlugin.dc.getUserByID(
Long.parseLong(p.getDiscordID())); Long.parseLong(p.getDiscordID()));
if (e.getValue()) if (e.getValue())
user.addRole(role); user.addRole(role);
@ -149,7 +149,7 @@ class MCListener implements Listener {
: event.getSender().getName(); : event.getSender().getName();
//Channel channel = ChromaGamerBase.getFromSender(event.getSender()).channel().get(); - TODO //Channel channel = ChromaGamerBase.getFromSender(event.getSender()).channel().get(); - TODO
val yeehaw = DiscordPlugin.mainServer.getEmojiByName("YEEHAW"); val yeehaw = DiscordPlugin.mainServer.getEmojiByName("YEEHAW");
MCChatUtils.forAllMCChat(MCChatUtils.send(name + (yeehaw != null ? " <:YEEHAW:" + yeehaw.getStringID() + ">s" : " YEEHAWs"))); MCChatUtils.forAllMCChat(MCChatUtils.send(name + (yeehaw != null ? " <:YEEHAW:" + yeehaw.getId().asString() + ">s" : " YEEHAWs")));
} }
@EventHandler @EventHandler

View file

@ -9,6 +9,9 @@ import buttondevteam.lib.TBMCSystemChatEvent;
import buttondevteam.lib.architecture.Component; import buttondevteam.lib.architecture.Component;
import buttondevteam.lib.architecture.ConfigData; import buttondevteam.lib.architecture.ConfigData;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import discord4j.core.event.domain.message.MessageCreateEvent;
import discord4j.core.object.entity.MessageChannel;
import discord4j.core.object.util.Snowflake;
import lombok.Getter; import lombok.Getter;
import lombok.val; import lombok.val;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@ -23,7 +26,8 @@ import java.util.stream.Collectors;
* Provides Minecraft chat connection to Discord. Commands may be used either in a public chat (limited) or in a DM. * Provides Minecraft chat connection to Discord. Commands may be used either in a public chat (limited) or in a DM.
*/ */
public class MinecraftChatModule extends Component<DiscordPlugin> { public class MinecraftChatModule extends Component<DiscordPlugin> {
private @Getter MCChatListener listener; private @Getter
MCChatListener listener;
/*public MCChatListener getListener() { //It doesn't want to generate /*public MCChatListener getListener() { //It doesn't want to generate
return listener; - And now ButtonProcessor didn't look beyond this - return instead of continue... return listener; - And now ButtonProcessor didn't look beyond this - return instead of continue...
@ -58,11 +62,20 @@ public class MinecraftChatModule extends Component<DiscordPlugin> {
return getConfig().getData("excludedPlugins", new String[]{"ProtocolLib", "LibsDisguises", "JourneyMapServer"}); return getConfig().getData("excludedPlugins", new String[]{"ProtocolLib", "LibsDisguises", "JourneyMapServer"});
} }
/**
* If this setting is on then players logged in through the 'mcchat' command will be able to teleport using plugin commands.
* They can then use commands like /tpahere to teleport others to that place.<br />
* If this is off, then teleporting will have no effect.
*/
public ConfigData<Boolean> allowFakePlayerTeleports() {
return getConfig().getData("allowFakePlayerTeleports", false);
}
@Override @Override
protected void enable() { protected void enable() {
if (DPUtils.disableIfConfigError(this, chatChannel())) return; if (DPUtils.disableIfConfigError(this, chatChannel())) return;
listener = new MCChatListener(this); listener = new MCChatListener(this);
DiscordPlugin.dc.getDispatcher().registerListener(listener); DiscordPlugin.dc.getEventDispatcher().on(MessageCreateEvent.class).subscribe(listener::handleDiscord);
TBMCCoreAPI.RegisterEventsForExceptions(listener, getPlugin()); TBMCCoreAPI.RegisterEventsForExceptions(listener, getPlugin());
TBMCCoreAPI.RegisterEventsForExceptions(new MCListener(this), getPlugin());//These get undone if restarting/resetting - it will ignore events if disabled TBMCCoreAPI.RegisterEventsForExceptions(new MCListener(this), getPlugin());//These get undone if restarting/resetting - it will ignore events if disabled
getPlugin().getManager().registerCommand(new MCChatCommand()); getPlugin().getManager().registerCommand(new MCChatCommand());
@ -76,17 +89,17 @@ public class MinecraftChatModule extends Component<DiscordPlugin> {
for (val chconkey : chconkeys) { for (val chconkey : chconkeys) {
val chcon = chcons.getConfigurationSection(chconkey); val chcon = chcons.getConfigurationSection(chconkey);
val mcch = Channel.getChannels().filter(ch -> ch.ID.equals(chcon.getString("mcchid"))).findAny(); val mcch = Channel.getChannels().filter(ch -> ch.ID.equals(chcon.getString("mcchid"))).findAny();
val ch = DiscordPlugin.dc.getChannelByID(chcon.getLong("chid")); val ch = DiscordPlugin.dc.getChannelById(Snowflake.of(chcon.getLong("chid"))).block();
val did = chcon.getLong("did"); val did = chcon.getLong("did");
val user = DiscordPlugin.dc.fetchUser(did); val user = DiscordPlugin.dc.getUserById(Snowflake.of(did)).block();
val groupid = chcon.getString("groupid"); val groupid = chcon.getString("groupid");
val toggles = chcon.getInt("toggles"); val toggles = chcon.getInt("toggles");
val brtoggles = chcon.getStringList("brtoggles"); val brtoggles = chcon.getStringList("brtoggles");
if (!mcch.isPresent() || ch == null || user == null || groupid == null) if (!mcch.isPresent() || ch == null || user == null || groupid == null)
continue; continue;
Bukkit.getScheduler().runTask(getPlugin(), () -> { //<-- Needed because of occasional ConcurrentModificationExceptions when creating the player (PermissibleBase) Bukkit.getScheduler().runTask(getPlugin(), () -> { //<-- Needed because of occasional ConcurrentModificationExceptions when creating the player (PermissibleBase)
val dcp = new DiscordConnectedPlayer(user, ch, UUID.fromString(chcon.getString("mcuid")), chcon.getString("mcname")); val dcp = new DiscordConnectedPlayer(user, (MessageChannel) ch, UUID.fromString(chcon.getString("mcuid")), chcon.getString("mcname"), this);
MCChatCustom.addCustomChat(ch, groupid, mcch.get(), user, dcp, toggles, brtoggles.stream().map(TBMCSystemChatEvent.BroadcastTarget::get).filter(Objects::nonNull).collect(Collectors.toSet())); MCChatCustom.addCustomChat((MessageChannel) ch, groupid, mcch.get(), user, dcp, toggles, brtoggles.stream().map(TBMCSystemChatEvent.BroadcastTarget::get).filter(Objects::nonNull).collect(Collectors.toSet()));
}); });
} }
} }
@ -97,10 +110,10 @@ public class MinecraftChatModule extends Component<DiscordPlugin> {
val chcons = MCChatCustom.getCustomChats(); val chcons = MCChatCustom.getCustomChats();
val chconsc = getConfig().getConfig().createSection("chcons"); val chconsc = getConfig().getConfig().createSection("chcons");
for (val chcon : chcons) { for (val chcon : chcons) {
val chconc = chconsc.createSection(chcon.channel.getStringID()); val chconc = chconsc.createSection(chcon.channel.getId().asString());
chconc.set("mcchid", chcon.mcchannel.ID); chconc.set("mcchid", chcon.mcchannel.ID);
chconc.set("chid", chcon.channel.getLongID()); chconc.set("chid", chcon.channel.getId().asLong());
chconc.set("did", chcon.user.getLongID()); chconc.set("did", chcon.user.getId().asLong());
chconc.set("mcuid", chcon.dcp.getUniqueId().toString()); chconc.set("mcuid", chcon.dcp.getUniqueId().toString());
chconc.set("mcname", chcon.dcp.getName()); chconc.set("mcname", chcon.dcp.getName());
chconc.set("groupid", chcon.groupID); chconc.set("groupid", chcon.groupID);

View file

@ -1,6 +1,10 @@
package buttondevteam.discordplugin.playerfaker; package buttondevteam.discordplugin.playerfaker;
import buttondevteam.discordplugin.DiscordPlugin;
import buttondevteam.discordplugin.DiscordSenderBase; import buttondevteam.discordplugin.DiscordSenderBase;
import buttondevteam.discordplugin.mcchat.MinecraftChatModule;
import discord4j.core.object.entity.MessageChannel;
import discord4j.core.object.entity.User;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import org.bukkit.*; import org.bukkit.*;
@ -11,8 +15,6 @@ import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
import org.bukkit.metadata.MetadataValue; import org.bukkit.metadata.MetadataValue;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
import sx.blah.discord.handle.obj.IUser;
import sx.blah.discord.handle.obj.MessageChannel;
import java.util.*; import java.util.*;
@ -20,10 +22,11 @@ import java.util.*;
@Setter @Setter
@SuppressWarnings("deprecated") @SuppressWarnings("deprecated")
public abstract class DiscordEntity extends DiscordSenderBase implements Entity { public abstract class DiscordEntity extends DiscordSenderBase implements Entity {
protected DiscordEntity(IUser user, MessageChannel channel, int entityId, UUID uuid) { protected DiscordEntity(User user, MessageChannel channel, int entityId, UUID uuid, MinecraftChatModule module) {
super(user, channel); super(user, channel);
this.entityId = entityId; this.entityId = entityId;
uniqueId = uuid; uniqueId = uuid;
this.module = module;
} }
private HashMap<String, MetadataValue> metadata = new HashMap<String, MetadataValue>(); private HashMap<String, MetadataValue> metadata = new HashMap<String, MetadataValue>();
@ -34,6 +37,7 @@ public abstract class DiscordEntity extends DiscordSenderBase implements Entity
private EntityDamageEvent lastDamageCause; private EntityDamageEvent lastDamageCause;
private final Set<String> scoreboardTags = new HashSet<String>(); private final Set<String> scoreboardTags = new HashSet<String>();
private final UUID uniqueId; private final UUID uniqueId;
private final MinecraftChatModule module;
@Override @Override
public void setMetadata(String metadataKey, MetadataValue newMetadataValue) { public void setMetadata(String metadataKey, MetadataValue newMetadataValue) {
@ -42,7 +46,7 @@ public abstract class DiscordEntity extends DiscordSenderBase implements Entity
@Override @Override
public List<MetadataValue> getMetadata(String metadataKey) { public List<MetadataValue> getMetadata(String metadataKey) {
return Arrays.asList(metadata.get(metadataKey)); // Who needs multiple data anyways return Collections.singletonList(metadata.get(metadataKey)); // Who needs multiple data anyways
} }
@Override @Override
@ -91,31 +95,35 @@ public abstract class DiscordEntity extends DiscordSenderBase implements Entity
@Override @Override
public boolean teleport(Location location) { public boolean teleport(Location location) {
this.location = location; if (module.allowFakePlayerTeleports().get())
this.location = location;
return true; return true;
} }
@Override @Override
public boolean teleport(Location location, TeleportCause cause) { public boolean teleport(Location location, TeleportCause cause) {
this.location = location; if (module.allowFakePlayerTeleports().get())
this.location = location;
return true; return true;
} }
@Override @Override
public boolean teleport(Entity destination) { public boolean teleport(Entity destination) {
this.location = destination.getLocation(); if (module.allowFakePlayerTeleports().get())
this.location = destination.getLocation();
return true; return true;
} }
@Override @Override
public boolean teleport(Entity destination, TeleportCause cause) { public boolean teleport(Entity destination, TeleportCause cause) {
this.location = destination.getLocation(); if (module.allowFakePlayerTeleports().get())
this.location = destination.getLocation();
return true; return true;
} }
@Override @Override
public List<Entity> getNearbyEntities(double x, double y, double z) { public List<Entity> getNearbyEntities(double x, double y, double z) {
return Arrays.asList(); return Collections.emptyList();
} }
@Override @Override
@ -163,7 +171,7 @@ public abstract class DiscordEntity extends DiscordSenderBase implements Entity
@Override @Override
public List<Entity> getPassengers() { public List<Entity> getPassengers() {
return Arrays.asList(); return Collections.emptyList();
} }
@Override @Override

View file

@ -1,6 +1,9 @@
package buttondevteam.discordplugin.playerfaker; package buttondevteam.discordplugin.playerfaker;
import buttondevteam.discordplugin.DiscordPlugin; import buttondevteam.discordplugin.DiscordPlugin;
import buttondevteam.discordplugin.mcchat.MinecraftChatModule;
import discord4j.core.object.entity.MessageChannel;
import discord4j.core.object.entity.User;
import lombok.Getter; import lombok.Getter;
import lombok.experimental.Delegate; import lombok.experimental.Delegate;
import org.bukkit.*; import org.bukkit.*;
@ -16,16 +19,14 @@ import org.bukkit.map.MapView;
import org.bukkit.permissions.PermissibleBase; import org.bukkit.permissions.PermissibleBase;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import org.bukkit.scoreboard.Scoreboard; import org.bukkit.scoreboard.Scoreboard;
import sx.blah.discord.handle.obj.IUser;
import sx.blah.discord.handle.obj.MessageChannel;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.util.*; import java.util.*;
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
public class DiscordFakePlayer extends DiscordHumanEntity implements Player { public class DiscordFakePlayer extends DiscordHumanEntity implements Player {
protected DiscordFakePlayer(IUser user, MessageChannel channel, int entityId, UUID uuid, String mcname) { protected DiscordFakePlayer(User user, MessageChannel channel, int entityId, UUID uuid, String mcname, MinecraftChatModule module) {
super(user, channel, entityId, uuid); super(user, channel, entityId, uuid, module);
perm = new PermissibleBase(Bukkit.getOfflinePlayer(uuid)); perm = new PermissibleBase(Bukkit.getOfflinePlayer(uuid));
name = mcname; name = mcname;
} }
@ -42,7 +43,7 @@ public class DiscordFakePlayer extends DiscordHumanEntity implements Player {
@Override @Override
public String getCustomName() { public String getCustomName() {
return user.getName(); return user.getUsername();
} }
@Override @Override
@ -127,7 +128,7 @@ public class DiscordFakePlayer extends DiscordHumanEntity implements Player {
@Override @Override
public String getDisplayName() { public String getDisplayName() {
return user.getDisplayName(DiscordPlugin.mainServer); return Objects.requireNonNull(user.asMember(DiscordPlugin.mainServer.getId()).block()).getDisplayName();
} }
@Override @Override

View file

@ -1,5 +1,8 @@
package buttondevteam.discordplugin.playerfaker; package buttondevteam.discordplugin.playerfaker;
import buttondevteam.discordplugin.mcchat.MinecraftChatModule;
import discord4j.core.object.entity.MessageChannel;
import discord4j.core.object.entity.User;
import org.bukkit.GameMode; import org.bukkit.GameMode;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
@ -8,14 +11,12 @@ import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Villager; import org.bukkit.entity.Villager;
import org.bukkit.inventory.*; import org.bukkit.inventory.*;
import org.bukkit.inventory.InventoryView.Property; import org.bukkit.inventory.InventoryView.Property;
import sx.blah.discord.handle.obj.IUser;
import sx.blah.discord.handle.obj.MessageChannel;
import java.util.UUID; import java.util.UUID;
public abstract class DiscordHumanEntity extends DiscordLivingEntity implements HumanEntity { public abstract class DiscordHumanEntity extends DiscordLivingEntity implements HumanEntity {
protected DiscordHumanEntity(IUser user, MessageChannel channel, int entityId, UUID uuid) { protected DiscordHumanEntity(User user, MessageChannel channel, int entityId, UUID uuid, MinecraftChatModule module) {
super(user, channel, entityId, uuid); super(user, channel, entityId, uuid, module);
} }
private PlayerInventory inv = new DiscordPlayerInventory(this); private PlayerInventory inv = new DiscordPlayerInventory(this);

View file

@ -1,5 +1,8 @@
package buttondevteam.discordplugin.playerfaker; package buttondevteam.discordplugin.playerfaker;
import buttondevteam.discordplugin.mcchat.MinecraftChatModule;
import discord4j.core.object.entity.MessageChannel;
import discord4j.core.object.entity.User;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import org.bukkit.Location; import org.bukkit.Location;
@ -16,15 +19,13 @@ import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffect; import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType; import org.bukkit.potion.PotionEffectType;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
import sx.blah.discord.handle.obj.IUser;
import sx.blah.discord.handle.obj.MessageChannel;
import java.util.*; import java.util.*;
public abstract class DiscordLivingEntity extends DiscordEntity implements LivingEntity { public abstract class DiscordLivingEntity extends DiscordEntity implements LivingEntity {
protected DiscordLivingEntity(IUser user, MessageChannel channel, int entityId, UUID uuid) { protected DiscordLivingEntity(User user, MessageChannel channel, int entityId, UUID uuid, MinecraftChatModule module) {
super(user, channel, entityId, uuid); super(user, channel, entityId, uuid, module);
} }
private @Getter EntityEquipment equipment = new DiscordEntityEquipment(this); private @Getter EntityEquipment equipment = new DiscordEntityEquipment(this);