Finished private Minecraft chat, lots of bug fixes #42
7 changed files with 97 additions and 75 deletions
|
@ -1,12 +1,13 @@
|
|||
package buttondevteam.discordplugin;
|
||||
|
||||
import buttondevteam.discordplugin.listeners.MCChatListener;
|
||||
import buttondevteam.lib.player.ChromaGamerBase;
|
||||
import buttondevteam.lib.player.PlayerData;
|
||||
import buttondevteam.lib.player.UserClass;
|
||||
|
||||
@UserClass(foldername = "discord")
|
||||
public class DiscordPlayer extends ChromaGamerBase {
|
||||
private String did;
|
||||
// private @Getter @Setter boolean minecraftChatEnabled;
|
||||
|
||||
public DiscordPlayer() {
|
||||
}
|
||||
|
@ -17,7 +18,11 @@ public class DiscordPlayer extends ChromaGamerBase {
|
|||
return did;
|
||||
}
|
||||
|
||||
public PlayerData<Boolean> minecraftChat() {
|
||||
return data(false);
|
||||
/**
|
||||
* 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)}
|
||||
*/
|
||||
public boolean isMinecraftChatEnabled() {
|
||||
return MCChatListener.isMinecraftChatEnabled(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -256,7 +256,8 @@ public class DiscordPlugin extends JavaPlugin implements IListener<ReadyEvent> {
|
|||
if (channel == chatchannel)
|
||||
MCChatListener.resetLastMessage(); // If this is a chat message, it'll be set again
|
||||
final String content = TBMCCoreAPI.IsTestServer() && channel != chatchannel || channel == botroomchannel // Both are the same for testing
|
||||
? "*The following message is from a test server*\n" + message : message;
|
||||
|| channel.isPrivate() //
|
||||
? "*The following message is from a test server*\n" + message : message;
|
||||
return perform(
|
||||
() -> embed == null ? channel.sendMessage(content) : channel.sendMessage(content, embed, false));
|
||||
} catch (Exception e) {
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package buttondevteam.discordplugin.commands;
|
||||
|
||||
import buttondevteam.discordplugin.DiscordPlayer;
|
||||
import buttondevteam.discordplugin.DiscordPlugin;
|
||||
import buttondevteam.discordplugin.listeners.MCChatListener;
|
||||
import buttondevteam.lib.TBMCCoreAPI;
|
||||
import buttondevteam.lib.player.PlayerData;
|
||||
import sx.blah.discord.handle.obj.IMessage;
|
||||
|
||||
public class MCChatCommand extends DiscordCommandBase {
|
||||
|
@ -16,17 +16,18 @@ public class MCChatCommand extends DiscordCommandBase {
|
|||
@Override
|
||||
public void run(IMessage message, String args) {
|
||||
if (!message.getChannel().isPrivate()) {
|
||||
message.reply("This command can only be issued in a direct message with the bot.");
|
||||
DiscordPlugin.sendMessageToChannel(message.getChannel(),
|
||||
"This command can only be issued in a direct message with the bot.");
|
||||
return;
|
||||
}
|
||||
try (final DiscordPlayer user = DiscordPlayer.getUser(message.getAuthor().getStringID(), DiscordPlayer.class)) {
|
||||
PlayerData<Boolean> mcchat = user.minecraftChat();
|
||||
mcchat.set(!mcchat.get());
|
||||
MCChatListener.privateMCChat(message.getChannel(), mcchat.get(), message.getAuthor(), user);
|
||||
message.reply("Minecraft chat " + (mcchat.get() //
|
||||
? "enabled. Use '" + message.getClient().getOurUser().mention()
|
||||
+ " mcchat' (with the mention) to disable." //
|
||||
: "disabled."));
|
||||
boolean mcchat = !user.isMinecraftChatEnabled();
|
||||
MCChatListener.privateMCChat(message.getChannel(), mcchat, message.getAuthor(), user);
|
||||
DiscordPlugin.sendMessageToChannel(message.getChannel(),
|
||||
"Minecraft chat " + (mcchat //
|
||||
? "enabled. Use '" + message.getClient().getOurUser().mention()
|
||||
+ " mcchat' (with the mention) to disable." //
|
||||
: "disabled."));
|
||||
} catch (Exception e) {
|
||||
TBMCCoreAPI.SendException("Error while setting mcchat for user" + message.getAuthor().getName(), e);
|
||||
}
|
||||
|
|
|
@ -59,13 +59,10 @@ public class CommandListener {
|
|||
if (event.getMessage().getAuthor().isBot())
|
||||
return;
|
||||
final IChannel channel = event.getMessage().getChannel();
|
||||
if (!channel.getStringID().equals(DiscordPlugin.botchannel.getStringID())
|
||||
&& (!channel.isPrivate() || DiscordPlugin.checkIfSomeoneIsTestingWhileWeArent()))
|
||||
if (!channel.getStringID().equals(DiscordPlugin.botchannel.getStringID()))
|
||||
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
|
||||
if (DiscordPlayer.getUser(event.getAuthor().getStringID(), DiscordPlayer.class).minecraftChat().get()) // Let the MCChatListener handle it
|
||||
return;
|
||||
event.getMessage().getChannel().setTypingStatus(true); // Fun
|
||||
runCommand(event.getMessage(), true);
|
||||
}
|
||||
|
@ -84,8 +81,8 @@ public class CommandListener {
|
|||
DiscordPlugin.sendMessageToChannel(event.getMessage().getChannel(), serverReadyStrings[next]);
|
||||
}
|
||||
if (!event.getMessage().getChannel().isPrivate() //
|
||||
|| DiscordPlayer.getUser(event.getAuthor().getStringID(), DiscordPlayer.class).minecraftChat()
|
||||
.get()
|
||||
|| DiscordPlayer.getUser(event.getAuthor().getStringID(), DiscordPlayer.class)
|
||||
.isMinecraftChatEnabled()
|
||||
|| DiscordPlugin.checkIfSomeoneIsTestingWhileWeArent())
|
||||
return;
|
||||
if (event.getMessage().getAuthor().isBot())
|
||||
|
|
|
@ -4,11 +4,12 @@ import java.awt.Color;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.UUID;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
|
@ -75,7 +76,7 @@ public class MCChatListener implements Listener, IListener<MessageReceivedEvent>
|
|||
final IUser iUser = data.channel.getUsersHere().stream()
|
||||
.filter(u -> u.getLongID() != u.getClient().getOurUser().getLongID()).findFirst().get(); // Doesn't support group DMs
|
||||
final DiscordPlayer user = DiscordPlayer.getUser(iUser.getStringID(), DiscordPlayer.class);
|
||||
if (user.minecraftChat().get() && e.shouldSendTo(getSender(data.channel, iUser, user)))
|
||||
if (user.isMinecraftChatEnabled() && e.shouldSendTo(getSender(data.channel, iUser, user)))
|
||||
doit.accept(data);
|
||||
}
|
||||
} // TODO: Author URL
|
||||
|
@ -132,11 +133,11 @@ public class MCChatListener implements Listener, IListener<MessageReceivedEvent>
|
|||
if (start) {
|
||||
val sender = new DiscordConnectedPlayer(user, channel, mcp.getUUID());
|
||||
ConnectedSenders.put(user.getStringID(), sender);
|
||||
if (p == null)// If the player is online, that takes precedence
|
||||
if (p == null)// Player is offline - If the player is online, that takes precedence
|
||||
Bukkit.getPluginManager().callEvent(new PlayerJoinEvent(sender, ""));
|
||||
} else {
|
||||
val sender = ConnectedSenders.remove(user.getStringID());
|
||||
if (p == null)// If the player is online, that takes precedence
|
||||
if (p == null)// Player is offline - If the player is online, that takes precedence
|
||||
Bukkit.getPluginManager().callEvent(new PlayerQuitEvent(sender, ""));
|
||||
}
|
||||
}
|
||||
|
@ -145,7 +146,6 @@ public class MCChatListener implements Listener, IListener<MessageReceivedEvent>
|
|||
: lastmsgPerUser.removeIf(lmd -> lmd.channel.getLongID() == channel.getLongID());
|
||||
}
|
||||
|
||||
//
|
||||
// ......................DiscordSender....DiscordConnectedPlayer.DiscordPlayerSender
|
||||
// Offline public chat......x............................................
|
||||
// Online public chat.......x...........................................x
|
||||
|
@ -155,10 +155,21 @@ public class MCChatListener implements Listener, IListener<MessageReceivedEvent>
|
|||
// 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 online and disabling private chat, don't logout
|
||||
// The maps may not contain the senders except for DiscordPlayerSender
|
||||
// The maps may not contain the senders for UnconnectedSenders
|
||||
|
||||
public static boolean isMinecraftChatEnabled(DiscordPlayer dp) {
|
||||
return lastmsgPerUser.stream().anyMatch(
|
||||
lmd -> ((IPrivateChannel) lmd.channel).getRecipient().getStringID().equals(dp.getDiscordID()));
|
||||
}
|
||||
|
||||
/**
|
||||
* May contain P<DiscordID> as key for public chat
|
||||
*/
|
||||
public static final HashMap<String, DiscordSender> UnconnectedSenders = new HashMap<>();
|
||||
public static final HashMap<String, DiscordConnectedPlayer> ConnectedSenders = new HashMap<>();
|
||||
/**
|
||||
* May contain P<DiscordID> as key for public chat
|
||||
*/
|
||||
public static final HashMap<String, DiscordPlayerSender> OnlineSenders = new HashMap<>();
|
||||
public static short ListC = 0;
|
||||
|
||||
|
@ -166,12 +177,18 @@ public class MCChatListener implements Listener, IListener<MessageReceivedEvent>
|
|||
(lastmsgdata == null ? lastmsgdata = new LastMsgData(DiscordPlugin.chatchannel) : lastmsgdata).message = null; // Don't set the whole object to null, the player and channel information should
|
||||
} // be preserved
|
||||
|
||||
public static void sendSystemMessageToChat(String msg) {
|
||||
DiscordPlugin.sendMessageToChannel(DiscordPlugin.chatchannel, msg);
|
||||
for (LastMsgData data : lastmsgPerUser)
|
||||
DiscordPlugin.sendMessageToChannel(data.channel, msg);
|
||||
}
|
||||
|
||||
@Override // Discord
|
||||
public void handle(MessageReceivedEvent event) {
|
||||
val author = event.getMessage().getAuthor();
|
||||
val user = DiscordPlayer.getUser(author.getStringID(), DiscordPlayer.class);
|
||||
if (!event.getMessage().getChannel().getStringID().equals(DiscordPlugin.chatchannel.getStringID())
|
||||
&& !(event.getMessage().getChannel().isPrivate() && user.minecraftChat().get()
|
||||
&& !(event.getMessage().getChannel().isPrivate() && user.isMinecraftChatEnabled()
|
||||
&& !DiscordPlugin.checkIfSomeoneIsTestingWhileWeArent()))
|
||||
return;
|
||||
resetLastMessage();
|
||||
|
@ -200,12 +217,13 @@ public class MCChatListener implements Listener, IListener<MessageReceivedEvent>
|
|||
if (dsender instanceof DiscordSender && !Arrays.stream(UnconnectedCmds)
|
||||
.anyMatch(s -> cmd.equals(s) || cmd.startsWith(s + " "))) {
|
||||
// Command not whitelisted
|
||||
dsender.sendMessage( // TODO
|
||||
"Sorry, you need to be online on the server and have your accounts connected, you can only access these commands:\n"
|
||||
+ Arrays.stream(UnconnectedCmds).map(uc -> "/" + uc)
|
||||
.collect(Collectors.joining(", "))
|
||||
+ "\nTo connect your accounts, use @ChromaBot connect in "
|
||||
+ DiscordPlugin.botchannel.mention());
|
||||
dsender.sendMessage("Sorry, you can only access these commands:\n"
|
||||
+ Arrays.stream(UnconnectedCmds).map(uc -> "/" + uc).collect(Collectors.joining(", "))
|
||||
+ (user.getConnectedID(TBMCPlayer.class) == null
|
||||
? "\nTo access your commands, first please connect your accounts, using @ChromaBot connect in "
|
||||
+ DiscordPlugin.botchannel.mention()
|
||||
+ "\nThen you can access all of your regular commands (even offline) in private chat: DM me `mcchat`!"
|
||||
: "\nYou can access all of your regular commands (even offline) in private chat: DM me `mcchat`!"));
|
||||
return;
|
||||
}
|
||||
if (lastlist > 5) {
|
||||
|
@ -248,29 +266,18 @@ public class MCChatListener implements Listener, IListener<MessageReceivedEvent>
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T extends DiscordSenderBase> DiscordSenderBase getSender(IChannel channel, final IUser author,
|
||||
DiscordPlayer dp) {
|
||||
final DiscordSenderBase dsender;
|
||||
final Player mcp;
|
||||
final String cid;
|
||||
BiFunction<HashMap<String, T>, Supplier<T>, DiscordSenderBase> getsender = (senders, maker) -> {
|
||||
if (!senders.containsKey(author.getStringID()))
|
||||
senders.put(author.getStringID(), maker.get());
|
||||
return senders.get(author.getStringID());
|
||||
};
|
||||
if ((cid = dp.getConnectedID(TBMCPlayer.class)) != null) { // Connected?
|
||||
if ((mcp = Bukkit.getPlayer(UUID.fromString(cid))) != null) // Online? - Execute as ingame player
|
||||
dsender = getsender.apply((HashMap<String, T>) OnlineSenders,
|
||||
() -> (T) new DiscordPlayerSender(author, channel, mcp));
|
||||
else // Offline
|
||||
dsender = getsender.apply((HashMap<String, T>) ConnectedSenders,
|
||||
() -> (T) new DiscordConnectedPlayer(author, channel, UUID.fromString(cid)));
|
||||
} else { // Not connected
|
||||
TBMCPlayer p = dp.getAs(TBMCPlayer.class);
|
||||
dsender = getsender.apply((HashMap<String, T>) UnconnectedSenders,
|
||||
() -> (T) new DiscordSender(author, channel, p == null ? null : p.PlayerName().get())); // Display the playername, if found
|
||||
}
|
||||
return dsender;
|
||||
/**
|
||||
* 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 DiscordSenderBase getSender(IChannel channel, final IUser author, DiscordPlayer dp) {
|
||||
val key = (channel.isPrivate() ? "" : "P") + author.getStringID();
|
||||
return Stream.<Supplier<Optional<DiscordSenderBase>>>of( // https://stackoverflow.com/a/28833677/2703239
|
||||
() -> Optional.ofNullable(OnlineSenders.get(key)), // Find first non-null
|
||||
() -> Optional.ofNullable(ConnectedSenders.get(author.getStringID())), // This doesn't support it
|
||||
() -> Optional.ofNullable(UnconnectedSenders.get(key)), () -> {
|
||||
val dsender = new DiscordSender(author, channel);
|
||||
UnconnectedSenders.put(key, dsender);
|
||||
return Optional.of(dsender);
|
||||
}).map(Supplier::get).filter(Optional::isPresent).map(Optional::get).findFirst().get();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
package buttondevteam.discordplugin.listeners;
|
||||
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.PlayerDeathEvent;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.event.server.ServerCommandEvent;
|
||||
|
||||
import com.earth2me.essentials.CommandSource;
|
||||
|
@ -16,6 +19,7 @@ import buttondevteam.discordplugin.DiscordPlugin;
|
|||
import buttondevteam.discordplugin.commands.ConnectCommand;
|
||||
import buttondevteam.lib.TBMCCoreAPI;
|
||||
import buttondevteam.lib.player.*;
|
||||
import lombok.val;
|
||||
import net.ess3.api.events.*;
|
||||
import sx.blah.discord.handle.obj.IRole;
|
||||
import sx.blah.discord.handle.obj.IUser;
|
||||
|
@ -23,14 +27,22 @@ import sx.blah.discord.util.DiscordException;
|
|||
import sx.blah.discord.util.MissingPermissionsException;
|
||||
|
||||
public class MCListener implements Listener {
|
||||
@EventHandler
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onPlayerJoin(TBMCPlayerJoinEvent e) {
|
||||
if (e.getPlayer() instanceof DiscordConnectedPlayer)
|
||||
return; // Don't show the joined message for the fake player
|
||||
final Player p = e.getPlayer();
|
||||
DiscordPlayer dp = e.GetPlayer().getAs(DiscordPlayer.class);
|
||||
// if(dp!=null) //TODO
|
||||
// MCChatListener.OnlineSenders.put(dp.getDiscordID(), new DiscordPlayerSender(DiscordPlugin.dc.getUserByID(Long.parseLong(dp.getDiscordID()), channel, player))
|
||||
if (dp != null) {
|
||||
val user = DiscordPlugin.dc.getUserByID(Long.parseLong(dp.getDiscordID()));
|
||||
MCChatListener.OnlineSenders.put(dp.getDiscordID(),
|
||||
new DiscordPlayerSender(user, user.getOrCreatePMChannel(), p));
|
||||
MCChatListener.OnlineSenders.put("P" + dp.getDiscordID(),
|
||||
new DiscordPlayerSender(user, DiscordPlugin.chatchannel, p));
|
||||
MCChatListener.ConnectedSenders.values().stream()
|
||||
.filter(s -> s.getUniqueId().equals(e.getPlayer().getUniqueId())).findAny()
|
||||
.ifPresent(dcp -> Bukkit.getPluginManager().callEvent(new PlayerQuitEvent(dcp, "")));
|
||||
}
|
||||
if (ConnectCommand.WaitingToConnect.containsKey(e.GetPlayer().PlayerName().get())) {
|
||||
IUser user = DiscordPlugin.dc
|
||||
.getUserByID(Long.parseLong(ConnectCommand.WaitingToConnect.get(e.GetPlayer().PlayerName().get())));
|
||||
|
@ -38,18 +50,20 @@ public class MCListener implements Listener {
|
|||
+ " do /discord accept");
|
||||
p.sendMessage("§bIf it wasn't you, do /discord decline");
|
||||
}
|
||||
DiscordPlugin.sendMessageToChannel(DiscordPlugin.chatchannel,
|
||||
e.GetPlayer().PlayerName().get() + " joined the game");
|
||||
MCChatListener.sendSystemMessageToChat(e.GetPlayer().PlayerName().get() + " joined the game");
|
||||
MCChatListener.ListC = 0;
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onPlayerLeave(TBMCPlayerQuitEvent e) {
|
||||
if (MCChatListener.OnlineSenders.entrySet()
|
||||
.removeIf(entry -> entry.getValue().getUniqueId().equals(e.getPlayer().getUniqueId())))
|
||||
; // TODO
|
||||
DiscordPlugin.sendMessageToChannel(DiscordPlugin.chatchannel,
|
||||
e.GetPlayer().PlayerName().get() + " left the game");
|
||||
if (e.getPlayer() instanceof DiscordConnectedPlayer)
|
||||
return; // Only care about real users
|
||||
MCChatListener.OnlineSenders.entrySet()
|
||||
.removeIf(entry -> entry.getValue().getUniqueId().equals(e.getPlayer().getUniqueId()));
|
||||
MCChatListener.ConnectedSenders.values().stream()
|
||||
.filter(s -> s.getUniqueId().equals(e.getPlayer().getUniqueId())).findAny()
|
||||
.ifPresent(dcp -> Bukkit.getPluginManager().callEvent(new PlayerJoinEvent(dcp, "")));
|
||||
MCChatListener.sendSystemMessageToChat(e.GetPlayer().PlayerName().get() + " left the game");
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
|
@ -70,16 +84,15 @@ public class MCListener implements Listener {
|
|||
|
||||
@EventHandler(priority = EventPriority.LOW)
|
||||
public void onPlayerDeath(PlayerDeathEvent e) {
|
||||
DiscordPlugin.sendMessageToChannel(DiscordPlugin.chatchannel, e.getDeathMessage());
|
||||
MCChatListener.sendSystemMessageToChat(e.getDeathMessage());
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onPlayerAFK(AfkStatusChangeEvent e) {
|
||||
if (e.isCancelled())
|
||||
if (e.isCancelled() || !e.getAffected().getBase().isOnline())
|
||||
return;
|
||||
DiscordPlugin.sendMessageToChannel(DiscordPlugin.chatchannel,
|
||||
DiscordPlugin.sanitizeString(e.getAffected().getBase().getDisplayName()) + " is "
|
||||
+ (e.getValue() ? "now" : "no longer") + " AFK.");
|
||||
MCChatListener.sendSystemMessageToChat(DiscordPlugin.sanitizeString(e.getAffected().getBase().getDisplayName())
|
||||
+ " is " + (e.getValue() ? "now" : "no longer") + " AFK.");
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
|
|
|
@ -9,7 +9,6 @@ import org.bukkit.conversations.Conversation;
|
|||
import org.bukkit.conversations.ConversationAbandonedEvent;
|
||||
import org.bukkit.entity.*;
|
||||
import org.bukkit.event.player.AsyncPlayerChatEvent;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.map.MapView;
|
||||
import org.bukkit.permissions.PermissibleBase;
|
||||
import org.bukkit.permissions.ServerOperator;
|
||||
|
@ -29,7 +28,6 @@ public class DiscordFakePlayer extends DiscordHumanEntity implements Player {
|
|||
perm = new PermissibleBase(new ServerOperator() {
|
||||
private @Getter @Setter boolean op;
|
||||
});
|
||||
Bukkit.getPluginManager().callEvent(new PlayerJoinEvent(this, "Discord fake player joined"));
|
||||
}
|
||||
|
||||
@Delegate
|
||||
|
|
Loading…
Add table
Reference in a new issue