Fix some mcchat and a reset issue
Using ConcurrentHashMaps (#62) Add custom /list to hide vanished players (#120) Fixed /discord reset for non-Paper servers (#103)
This commit is contained in:
parent
56d13ebf9f
commit
891be91d69
6 changed files with 98 additions and 70 deletions
|
@ -100,7 +100,7 @@ public class FunModule extends Component<DiscordPlugin> implements Listener {
|
||||||
ListC = 0;
|
ListC = 0;
|
||||||
lastlist = 0;
|
lastlist = 0;
|
||||||
}
|
}
|
||||||
if (msglowercased.equals("list") && Bukkit.getOnlinePlayers().size() == lastlistp && ListC++ > 2) // Lowered already
|
if (msglowercased.equals("/list") && Bukkit.getOnlinePlayers().size() == lastlistp && ListC++ > 2) // Lowered already
|
||||||
{
|
{
|
||||||
DPUtils.reply(message, Mono.empty(), "stop it. You know the answer.").subscribe();
|
DPUtils.reply(message, Mono.empty(), "stop it. You know the answer.").subscribe();
|
||||||
lastlist = 0;
|
lastlist = 0;
|
||||||
|
|
|
@ -20,15 +20,17 @@ public class MCChatCustom {
|
||||||
/**
|
/**
|
||||||
* Used for town or nation chats or anything else
|
* Used for town or nation chats or anything else
|
||||||
*/
|
*/
|
||||||
static ArrayList<CustomLMD> lastmsgCustom = new ArrayList<>();
|
static final ArrayList<CustomLMD> lastmsgCustom = new ArrayList<>();
|
||||||
|
|
||||||
public static void addCustomChat(MessageChannel channel, String groupid, Channel mcchannel, User 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) {
|
synchronized (lastmsgCustom) {
|
||||||
((ChatRoom) mcchannel).joinRoom(dcp);
|
if (mcchannel instanceof ChatRoom) {
|
||||||
if (groupid == null) groupid = mcchannel.getGroupID(dcp);
|
((ChatRoom) mcchannel).joinRoom(dcp);
|
||||||
|
if (groupid == null) groupid = mcchannel.getGroupID(dcp);
|
||||||
|
}
|
||||||
|
val lmd = new CustomLMD(channel, user, groupid, mcchannel, dcp, toggles, brtoggles);
|
||||||
|
lastmsgCustom.add(lmd);
|
||||||
}
|
}
|
||||||
val lmd = new CustomLMD(channel, user, groupid, mcchannel, dcp, toggles, brtoggles);
|
|
||||||
lastmsgCustom.add(lmd);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean hasCustomChat(Snowflake channel) {
|
public static boolean hasCustomChat(Snowflake channel) {
|
||||||
|
@ -41,14 +43,16 @@ public class MCChatCustom {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean removeCustomChat(Snowflake channel) {
|
public static boolean removeCustomChat(Snowflake channel) {
|
||||||
MCChatUtils.lastmsgfromd.remove(channel.asLong());
|
synchronized (lastmsgCustom) {
|
||||||
return lastmsgCustom.removeIf(lmd -> {
|
MCChatUtils.lastmsgfromd.remove(channel.asLong());
|
||||||
if (lmd.channel.getId().asLong() != channel.asLong())
|
return lastmsgCustom.removeIf(lmd -> {
|
||||||
return false;
|
if (lmd.channel.getId().asLong() != channel.asLong())
|
||||||
if (lmd.mcchannel instanceof ChatRoom)
|
return false;
|
||||||
((ChatRoom) lmd.mcchannel).leaveRoom(lmd.dcp);
|
if (lmd.mcchannel instanceof ChatRoom)
|
||||||
return true;
|
((ChatRoom) lmd.mcchannel).leaveRoom(lmd.dcp);
|
||||||
});
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<CustomLMD> getCustomChats() {
|
public static List<CustomLMD> getCustomChats() {
|
||||||
|
|
|
@ -131,17 +131,19 @@ public class MCChatListener implements Listener {
|
||||||
doit.accept(data);
|
doit.accept(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
val iterator = MCChatCustom.lastmsgCustom.iterator();
|
synchronized (MCChatCustom.lastmsgCustom) {
|
||||||
while (iterator.hasNext()) {
|
val iterator = MCChatCustom.lastmsgCustom.iterator();
|
||||||
val lmd = iterator.next();
|
while (iterator.hasNext()) {
|
||||||
if ((e.isFromCommand() || isdifferentchannel.test(lmd.channel.getId())) //Test if msg is from Discord
|
val lmd = iterator.next();
|
||||||
&& 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
|
if ((e.isFromCommand() || isdifferentchannel.test(lmd.channel.getId())) //Test if msg is from Discord
|
||||||
&& e.getGroupID().equals(lmd.groupID)) { //Check if this is the group we want to test - #58
|
&& 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
|
||||||
if (e.shouldSendTo(lmd.dcp)) //Check original user's permissions
|
&& e.getGroupID().equals(lmd.groupID)) { //Check if this is the group we want to test - #58
|
||||||
doit.accept(lmd);
|
if (e.shouldSendTo(lmd.dcp)) //Check original user's permissions
|
||||||
else {
|
doit.accept(lmd);
|
||||||
iterator.remove(); //If the user no longer has permission, remove the connection
|
else {
|
||||||
lmd.channel.createMessage("The user no longer has permission to view the channel, connection removed.").subscribe();
|
iterator.remove(); //If the user no longer has permission, remove the connection
|
||||||
|
lmd.channel.createMessage("The user no longer has permission to view the channel, connection removed.").subscribe();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -217,7 +219,7 @@ public class MCChatListener implements Listener {
|
||||||
}
|
}
|
||||||
|
|
||||||
private BukkitTask rectask;
|
private BukkitTask rectask;
|
||||||
private LinkedBlockingQueue<MessageCreateEvent> recevents = new LinkedBlockingQueue<>();
|
private final LinkedBlockingQueue<MessageCreateEvent> recevents = new LinkedBlockingQueue<>();
|
||||||
private Runnable recrun;
|
private Runnable recrun;
|
||||||
private static Thread recthread;
|
private static Thread recthread;
|
||||||
|
|
||||||
|
@ -368,6 +370,7 @@ public class MCChatListener implements Listener {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
module.log(dsender.getName() + " ran from DC: /" + cmd);
|
module.log(dsender.getName() + " ran from DC: /" + cmd);
|
||||||
|
if (runCustomCommand(dsender, cmdlowercased)) return true;
|
||||||
val channel = clmd == null ? user.channel().get() : clmd.mcchannel;
|
val channel = clmd == null ? user.channel().get() : clmd.mcchannel;
|
||||||
val ev = new TBMCCommandPreprocessEvent(dsender, channel, dmessage, clmd == null ? dsender : clmd.dcp);
|
val ev = new TBMCCommandPreprocessEvent(dsender, channel, dmessage, clmd == null ? dsender : clmd.dcp);
|
||||||
Bukkit.getScheduler().runTask(DiscordPlugin.plugin, //Commands need to be run sync
|
Bukkit.getScheduler().runTask(DiscordPlugin.plugin, //Commands need to be run sync
|
||||||
|
@ -396,6 +399,17 @@ public class MCChatListener implements Listener {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean runCustomCommand(DiscordSenderBase dsender, String cmdlowercased) {
|
||||||
|
if (cmdlowercased.startsWith("list")) {
|
||||||
|
var players = Bukkit.getOnlinePlayers();
|
||||||
|
dsender.sendMessage("There are " + players.size() + " out of " + Bukkit.getMaxPlayers() + " players online.");
|
||||||
|
dsender.sendMessage("Players: " + players.stream().filter(MCChatUtils::checkEssentials)
|
||||||
|
.map(Player::getDisplayName).collect(Collectors.joining(", ")));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
private interface InterruptibleConsumer<T> {
|
private interface InterruptibleConsumer<T> {
|
||||||
void accept(T value) throws TimeoutException, InterruptedException;
|
void accept(T value) throws TimeoutException, InterruptedException;
|
||||||
|
|
|
@ -20,32 +20,34 @@ 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, User user, DiscordPlayer dp) {
|
public static boolean privateMCChat(MessageChannel channel, boolean start, User user, DiscordPlayer dp) {
|
||||||
TBMCPlayer mcp = dp.getAs(TBMCPlayer.class);
|
synchronized (MCChatUtils.ConnectedSenders) {
|
||||||
if (mcp != null) { // If the accounts aren't connected, can't make a connected sender
|
TBMCPlayer mcp = dp.getAs(TBMCPlayer.class);
|
||||||
val p = Bukkit.getPlayer(mcp.getUUID());
|
if (mcp != null) { // If the accounts aren't connected, can't make a connected sender
|
||||||
val op = Bukkit.getOfflinePlayer(mcp.getUUID());
|
val p = Bukkit.getPlayer(mcp.getUUID());
|
||||||
val mcm = ComponentManager.getIfEnabled(MinecraftChatModule.class);
|
val op = Bukkit.getOfflinePlayer(mcp.getUUID());
|
||||||
if (start) {
|
val mcm = ComponentManager.getIfEnabled(MinecraftChatModule.class);
|
||||||
val sender = DiscordConnectedPlayer.create(user, channel, mcp.getUUID(), op.getName(), mcm);
|
if (start) {
|
||||||
MCChatUtils.addSender(MCChatUtils.ConnectedSenders, user, sender);
|
val sender = DiscordConnectedPlayer.create(user, channel, mcp.getUUID(), op.getName(), mcm);
|
||||||
MCChatUtils.LoggedInPlayers.put(mcp.getUUID(), sender);
|
MCChatUtils.addSender(MCChatUtils.ConnectedSenders, user, sender);
|
||||||
if (p == null) // Player is offline - If the player is online, that takes precedence
|
MCChatUtils.LoggedInPlayers.put(mcp.getUUID(), sender);
|
||||||
MCChatUtils.callLoginEvents(sender);
|
if (p == null) // Player is offline - If the player is online, that takes precedence
|
||||||
} else {
|
MCChatUtils.callLoginEvents(sender);
|
||||||
val sender = MCChatUtils.removeSender(MCChatUtils.ConnectedSenders, channel.getId(), user);
|
} else {
|
||||||
assert sender != null;
|
val sender = MCChatUtils.removeSender(MCChatUtils.ConnectedSenders, channel.getId(), user);
|
||||||
MCChatUtils.LoggedInPlayers.remove(sender.getUniqueId());
|
assert sender != null;
|
||||||
if (p == null // Player is offline - If the player is online, that takes precedence
|
MCChatUtils.LoggedInPlayers.remove(sender.getUniqueId());
|
||||||
&& sender.isLoggedIn()) //Don't call the quit event if login failed
|
if (p == null // Player is offline - If the player is online, that takes precedence
|
||||||
MCChatUtils.callLogoutEvent(sender, true);
|
&& sender.isLoggedIn()) //Don't call the quit event if login failed
|
||||||
sender.setLoggedIn(false);
|
MCChatUtils.callLogoutEvent(sender, true);
|
||||||
}
|
sender.setLoggedIn(false);
|
||||||
} // ---- PermissionsEx warning is normal on logout ----
|
}
|
||||||
if (!start)
|
} // ---- PermissionsEx warning is normal on logout ----
|
||||||
MCChatUtils.lastmsgfromd.remove(channel.getId().asLong());
|
if (!start)
|
||||||
return start //
|
MCChatUtils.lastmsgfromd.remove(channel.getId().asLong());
|
||||||
? lastmsgPerUser.add(new MCChatUtils.LastMsgData(channel, user)) // Doesn't support group DMs
|
return start //
|
||||||
: lastmsgPerUser.removeIf(lmd -> lmd.channel.getId().asLong() == channel.getId().asLong());
|
? lastmsgPerUser.add(new MCChatUtils.LastMsgData(channel, user)) // Doesn't support group DMs
|
||||||
|
: lastmsgPerUser.removeIf(lmd -> lmd.channel.getId().asLong() == channel.getId().asLong());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isMinecraftChatEnabled(DiscordPlayer dp) {
|
public static boolean isMinecraftChatEnabled(DiscordPlayer dp) {
|
||||||
|
@ -59,11 +61,13 @@ public class MCChatPrivate {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void logoutAll() {
|
public static void logoutAll() {
|
||||||
for (val entry : MCChatUtils.ConnectedSenders.entrySet())
|
synchronized (MCChatUtils.ConnectedSenders) {
|
||||||
for (val valueEntry : entry.getValue().entrySet())
|
for (val entry : MCChatUtils.ConnectedSenders.entrySet())
|
||||||
if (MCChatUtils.getSender(MCChatUtils.OnlineSenders, valueEntry.getKey(), valueEntry.getValue().getUser()) == null) //If the player is online then the fake player was already logged out
|
for (val valueEntry : entry.getValue().entrySet())
|
||||||
MCChatUtils.callLogoutEvent(valueEntry.getValue(), false); //This is sync
|
if (MCChatUtils.getSender(MCChatUtils.OnlineSenders, valueEntry.getKey(), valueEntry.getValue().getUser()) == null) //If the player is online then the fake player was already logged out
|
||||||
MCChatUtils.ConnectedSenders.clear();
|
MCChatUtils.callLogoutEvent(valueEntry.getValue(), false); //This is sync
|
||||||
|
MCChatUtils.ConnectedSenders.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ import reactor.core.publisher.Mono;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
@ -45,13 +46,13 @@ public class MCChatUtils {
|
||||||
/**
|
/**
|
||||||
* May contain P<DiscordID> as key for public chat
|
* May contain P<DiscordID> as key for public chat
|
||||||
*/
|
*/
|
||||||
public static final HashMap<String, HashMap<Snowflake, DiscordSender>> UnconnectedSenders = new HashMap<>();
|
public static final ConcurrentHashMap<String, ConcurrentHashMap<Snowflake, DiscordSender>> UnconnectedSenders = new ConcurrentHashMap<>();
|
||||||
public static final HashMap<String, HashMap<Snowflake, DiscordConnectedPlayer>> ConnectedSenders = new HashMap<>();
|
public static final ConcurrentHashMap<String, ConcurrentHashMap<Snowflake, DiscordConnectedPlayer>> ConnectedSenders = new ConcurrentHashMap<>();
|
||||||
/**
|
/**
|
||||||
* May contain P<DiscordID> as key for public chat
|
* May contain P<DiscordID> as key for public chat
|
||||||
*/
|
*/
|
||||||
public static final HashMap<String, HashMap<Snowflake, DiscordPlayerSender>> OnlineSenders = new HashMap<>();
|
public static final ConcurrentHashMap<String, ConcurrentHashMap<Snowflake, DiscordPlayerSender>> OnlineSenders = new ConcurrentHashMap<>();
|
||||||
public static final HashMap<UUID, DiscordConnectedPlayer> LoggedInPlayers = new HashMap<>();
|
public static final ConcurrentHashMap<UUID, DiscordConnectedPlayer> LoggedInPlayers = new ConcurrentHashMap<>();
|
||||||
static @Nullable LastMsgData lastmsgdata;
|
static @Nullable LastMsgData lastmsgdata;
|
||||||
static LongObjectHashMap<Message> lastmsgfromd = new LongObjectHashMap<>(); // Last message sent by a Discord user, used for clearing checkmarks
|
static LongObjectHashMap<Message> lastmsgfromd = new LongObjectHashMap<>(); // Last message sent by a Discord user, used for clearing checkmarks
|
||||||
private static MinecraftChatModule module;
|
private static MinecraftChatModule module;
|
||||||
|
@ -104,28 +105,28 @@ public class MCChatUtils {
|
||||||
((TextChannel) lmd.channel).edit(tce -> tce.setTopic(String.join("\n----\n", s)).setReason("Player list update")).subscribe(); //Don't wait
|
((TextChannel) lmd.channel).edit(tce -> tce.setTopic(String.join("\n----\n", s)).setReason("Player list update")).subscribe(); //Don't wait
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean checkEssentials(Player p) {
|
static boolean checkEssentials(Player p) {
|
||||||
var ess = MainPlugin.ess;
|
var ess = MainPlugin.ess;
|
||||||
if (ess == null) return true;
|
if (ess == null) return true;
|
||||||
return !ess.getUser(p).isHidden();
|
return !ess.getUser(p).isHidden();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T extends DiscordSenderBase> T addSender(HashMap<String, HashMap<Snowflake, T>> senders,
|
public static <T extends DiscordSenderBase> T addSender(ConcurrentHashMap<String, ConcurrentHashMap<Snowflake, T>> senders,
|
||||||
User user, T sender) {
|
User user, T sender) {
|
||||||
return addSender(senders, user.getId().asString(), sender);
|
return addSender(senders, user.getId().asString(), sender);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T extends DiscordSenderBase> T addSender(HashMap<String, HashMap<Snowflake, T>> senders,
|
public static <T extends DiscordSenderBase> T addSender(ConcurrentHashMap<String, ConcurrentHashMap<Snowflake, T>> senders,
|
||||||
String did, T sender) {
|
String did, T sender) {
|
||||||
var map = senders.get(did);
|
var map = senders.get(did);
|
||||||
if (map == null)
|
if (map == null)
|
||||||
map = new HashMap<>();
|
map = new ConcurrentHashMap<>();
|
||||||
map.put(sender.getChannel().getId(), sender);
|
map.put(sender.getChannel().getId(), sender);
|
||||||
senders.put(did, map);
|
senders.put(did, map);
|
||||||
return sender;
|
return sender;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T extends DiscordSenderBase> T getSender(HashMap<String, HashMap<Snowflake, T>> senders,
|
public static <T extends DiscordSenderBase> T getSender(ConcurrentHashMap<String, ConcurrentHashMap<Snowflake, T>> senders,
|
||||||
Snowflake channel, User user) {
|
Snowflake channel, User user) {
|
||||||
var map = senders.get(user.getId().asString());
|
var map = senders.get(user.getId().asString());
|
||||||
if (map != null)
|
if (map != null)
|
||||||
|
@ -133,7 +134,7 @@ public class MCChatUtils {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T extends DiscordSenderBase> T removeSender(HashMap<String, HashMap<Snowflake, T>> senders,
|
public static <T extends DiscordSenderBase> T removeSender(ConcurrentHashMap<String, ConcurrentHashMap<Snowflake, T>> senders,
|
||||||
Snowflake channel, User user) {
|
Snowflake channel, User user) {
|
||||||
var map = senders.get(user.getId().asString());
|
var map = senders.get(user.getId().asString());
|
||||||
if (map != null)
|
if (map != null)
|
||||||
|
|
|
@ -74,7 +74,7 @@ public class DiscordMCCommand extends ICommand2MC {
|
||||||
"This command disables and then enables the plugin." //
|
"This command disables and then enables the plugin." //
|
||||||
})
|
})
|
||||||
public void reset(CommandSender sender) {
|
public void reset(CommandSender sender) {
|
||||||
Bukkit.getScheduler().runTaskAsynchronously(DiscordPlugin.plugin, () -> {
|
Runnable task = () -> {
|
||||||
if (!DiscordPlugin.plugin.tryReloadConfig()) {
|
if (!DiscordPlugin.plugin.tryReloadConfig()) {
|
||||||
sender.sendMessage("§cFailed to reload config so not resetting. Check the console.");
|
sender.sendMessage("§cFailed to reload config so not resetting. Check the console.");
|
||||||
return;
|
return;
|
||||||
|
@ -87,7 +87,12 @@ public class DiscordMCCommand extends ICommand2MC {
|
||||||
Bukkit.getPluginManager().enablePlugin(DiscordPlugin.plugin);
|
Bukkit.getPluginManager().enablePlugin(DiscordPlugin.plugin);
|
||||||
if (!(sender instanceof DiscordSenderBase)) //Sending to Discord errors
|
if (!(sender instanceof DiscordSenderBase)) //Sending to Discord errors
|
||||||
sender.sendMessage("§bReset finished!");
|
sender.sendMessage("§bReset finished!");
|
||||||
});
|
};
|
||||||
|
if (!Bukkit.getName().equals("Paper")) {
|
||||||
|
getPlugin().getLogger().warning("Async plugin events are not supported by the server, running on main thread");
|
||||||
|
Bukkit.getScheduler().runTask(DiscordPlugin.plugin, task);
|
||||||
|
} else
|
||||||
|
Bukkit.getScheduler().runTaskAsynchronously(DiscordPlugin.plugin, task);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Command2.Subcommand(helpText = {
|
@Command2.Subcommand(helpText = {
|
||||||
|
|
Loading…
Reference in a new issue