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:
Norbi Peti 2020-10-08 00:02:49 +02:00
parent 56d13ebf9f
commit 891be91d69
No known key found for this signature in database
GPG key ID: DBA4C4549A927E56
6 changed files with 98 additions and 70 deletions

View file

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

View file

@ -20,9 +20,10 @@ 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) {
synchronized (lastmsgCustom) {
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,6 +31,7 @@ public class MCChatCustom {
val lmd = new CustomLMD(channel, user, groupid, mcchannel, dcp, toggles, brtoggles); val lmd = new CustomLMD(channel, user, groupid, mcchannel, dcp, toggles, brtoggles);
lastmsgCustom.add(lmd); lastmsgCustom.add(lmd);
} }
}
public static boolean hasCustomChat(Snowflake channel) { public static boolean hasCustomChat(Snowflake channel) {
return lastmsgCustom.stream().anyMatch(lmd -> lmd.channel.getId().asLong() == channel.asLong()); return lastmsgCustom.stream().anyMatch(lmd -> lmd.channel.getId().asLong() == channel.asLong());
@ -41,6 +43,7 @@ public class MCChatCustom {
} }
public static boolean removeCustomChat(Snowflake channel) { public static boolean removeCustomChat(Snowflake channel) {
synchronized (lastmsgCustom) {
MCChatUtils.lastmsgfromd.remove(channel.asLong()); MCChatUtils.lastmsgfromd.remove(channel.asLong());
return lastmsgCustom.removeIf(lmd -> { return lastmsgCustom.removeIf(lmd -> {
if (lmd.channel.getId().asLong() != channel.asLong()) if (lmd.channel.getId().asLong() != channel.asLong())
@ -50,6 +53,7 @@ public class MCChatCustom {
return true; return true;
}); });
} }
}
public static List<CustomLMD> getCustomChats() { public static List<CustomLMD> getCustomChats() {
return Collections.unmodifiableList(lastmsgCustom); return Collections.unmodifiableList(lastmsgCustom);

View file

@ -131,6 +131,7 @@ public class MCChatListener implements Listener {
doit.accept(data); doit.accept(data);
} }
synchronized (MCChatCustom.lastmsgCustom) {
val iterator = MCChatCustom.lastmsgCustom.iterator(); val iterator = MCChatCustom.lastmsgCustom.iterator();
while (iterator.hasNext()) { while (iterator.hasNext()) {
val lmd = iterator.next(); val lmd = iterator.next();
@ -145,6 +146,7 @@ public class MCChatListener implements Listener {
} }
} }
} }
}
} catch (InterruptedException ex) { //Stop if interrupted anywhere } catch (InterruptedException ex) { //Stop if interrupted anywhere
sendtask.cancel(); sendtask.cancel();
sendtask = null; sendtask = null;
@ -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;

View file

@ -20,6 +20,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, User user, DiscordPlayer dp) { public static boolean privateMCChat(MessageChannel channel, boolean start, User user, DiscordPlayer dp) {
synchronized (MCChatUtils.ConnectedSenders) {
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());
@ -47,6 +48,7 @@ public class MCChatPrivate {
? 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.getId().asLong() == channel.getId().asLong()); : lastmsgPerUser.removeIf(lmd -> lmd.channel.getId().asLong() == channel.getId().asLong());
} }
}
public static boolean isMinecraftChatEnabled(DiscordPlayer dp) { public static boolean isMinecraftChatEnabled(DiscordPlayer dp) {
return isMinecraftChatEnabled(dp.getDiscordID()); return isMinecraftChatEnabled(dp.getDiscordID());
@ -59,11 +61,13 @@ public class MCChatPrivate {
} }
public static void logoutAll() { public static void logoutAll() {
synchronized (MCChatUtils.ConnectedSenders) {
for (val entry : MCChatUtils.ConnectedSenders.entrySet()) for (val entry : MCChatUtils.ConnectedSenders.entrySet())
for (val valueEntry : entry.getValue().entrySet()) for (val valueEntry : entry.getValue().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 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.callLogoutEvent(valueEntry.getValue(), false); //This is sync MCChatUtils.callLogoutEvent(valueEntry.getValue(), false); //This is sync
MCChatUtils.ConnectedSenders.clear(); MCChatUtils.ConnectedSenders.clear();
} }
}
} }

View file

@ -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&lt;DiscordID&gt; as key for public chat * May contain P&lt;DiscordID&gt; 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&lt;DiscordID&gt; as key for public chat * May contain P&lt;DiscordID&gt; 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)

View file

@ -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 = {