From b460a5da4dd8aa2d0b131529a55a97f19022e0b8 Mon Sep 17 00:00:00 2001 From: OptimisticDeving <173472493+OptimisticDeving@users.noreply.github.com> Date: Tue, 8 Jul 2025 21:37:56 +0000 Subject: [PATCH] Remove players immediately from channel listeners Fixes players not being able to receive messages after registering to a channel, rejoining and registering again. --- src/main/java/pw/kaboom/extras/Main.java | 2 + .../modules/player/PlayerMessaging.java | 56 +++++++++---------- 2 files changed, 27 insertions(+), 31 deletions(-) diff --git a/src/main/java/pw/kaboom/extras/Main.java b/src/main/java/pw/kaboom/extras/Main.java index 55487b5..3e23caa 100644 --- a/src/main/java/pw/kaboom/extras/Main.java +++ b/src/main/java/pw/kaboom/extras/Main.java @@ -94,6 +94,8 @@ public final class Main extends JavaPlugin { final Messenger messenger = this.getServer().getMessenger(); final PlayerMessaging playerMessaging = new PlayerMessaging(this); + this.getServer().getPluginManager().registerEvents(playerMessaging, this); + messenger.registerIncomingPluginChannel(this, PlayerMessaging.REGISTER, playerMessaging); messenger.registerIncomingPluginChannel(this, PlayerMessaging.UNREGISTER, playerMessaging); diff --git a/src/main/java/pw/kaboom/extras/modules/player/PlayerMessaging.java b/src/main/java/pw/kaboom/extras/modules/player/PlayerMessaging.java index bbfe0f2..461add5 100644 --- a/src/main/java/pw/kaboom/extras/modules/player/PlayerMessaging.java +++ b/src/main/java/pw/kaboom/extras/modules/player/PlayerMessaging.java @@ -5,6 +5,10 @@ import it.unimi.dsi.fastutil.io.FastByteArrayInputStream; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerQuitEvent; import org.bukkit.plugin.messaging.Messenger; import org.bukkit.plugin.messaging.PluginMessageListener; import org.jetbrains.annotations.NotNull; @@ -13,50 +17,20 @@ import pw.kaboom.extras.Main; import java.io.*; import java.nio.charset.StandardCharsets; import java.util.*; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; -public final class PlayerMessaging implements PluginMessageListener { +public final class PlayerMessaging implements PluginMessageListener, Listener { public static final String REGISTER = "extras:register"; public static final String UNREGISTER = "extras:unregister"; public static final String MESSAGE = "extras:message"; private static final Component ERROR = Component.text("Could not send plugin channel message.", NamedTextColor.RED); - private static final ScheduledExecutorService SCHEDULED_EXECUTOR_SERVICE = - Executors.newSingleThreadScheduledExecutor(); private static final byte END_CHAR_MASK = (byte) 0x80; private final Main plugin; public PlayerMessaging(final Main plugin) { this.plugin = plugin; - - SCHEDULED_EXECUTOR_SERVICE.scheduleAtFixedRate(() -> { - synchronized (this.listening) { - final Iterator>> iterator = - this.listening.entrySet().iterator(); - - while (iterator.hasNext()) { - final Map.Entry> entry = iterator.next(); - - final Set players = entry.getValue(); - synchronized (players) { - // try and avoid issues with other plugins causing player obj leaks - int onlineCount = 0; - - for (final Player player: players) { - if (!player.isOnline()) continue; - onlineCount++; - } - - if (onlineCount != 0) continue; - iterator.remove(); - } - } - } - }, 1, 1, TimeUnit.MINUTES); } private final Map> listening = Collections.synchronizedMap(new HashMap<>()); @@ -190,4 +164,24 @@ public final class PlayerMessaging implements PluginMessageListener { player.sendMessage(ERROR); } } + + @EventHandler(priority = EventPriority.MONITOR) + public void onPlayerQuit(PlayerQuitEvent event) { + final Player removedPlayer = event.getPlayer(); + + synchronized (this.listening) { + final Iterator>> listeningIterator = + this.listening.entrySet().iterator(); + + while (listeningIterator.hasNext()) { + final Map.Entry> entry = listeningIterator.next(); + final Set players = entry.getValue(); + synchronized (players) { + players.remove(removedPlayer); + + if (players.isEmpty()) listeningIterator.remove(); + } + } + } + } }