From 6e8828f606c46638a19f1933b8c8de1bb5b1c303 Mon Sep 17 00:00:00 2001 From: RootBeer Date: Sat, 14 Nov 2026 21:19:50 -0500 Subject: [PATCH] Handle overlapping sessions of the same player A player can rejoin before their previous session has been removed completely, e.g. on Folia. Since Player#equals only compares uuids, the old session's quit removed the new session's packet handler, the new session's join threw because a packet handler was already registered, and the old session's inventory close closed the new session's window. --- .../invui/internal/network/PacketListener.java | 17 ++++++++++++----- .../xenondevs/invui/window/WindowManager.java | 3 ++- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/invui/src/main/java/xyz/xenondevs/invui/internal/network/PacketListener.java b/invui/src/main/java/xyz/xenondevs/invui/internal/network/PacketListener.java index 575e11c4..bbee2448 100644 --- a/invui/src/main/java/xyz/xenondevs/invui/internal/network/PacketListener.java +++ b/invui/src/main/java/xyz/xenondevs/invui/internal/network/PacketListener.java @@ -92,12 +92,17 @@ private void handleJoin(PlayerJoinEvent event) { @EventHandler(priority = EventPriority.MONITOR) private void handleQuit(PlayerQuitEvent event) { - packetHandlers.remove(event.getPlayer().getUniqueId()); + var player = event.getPlayer(); + packetHandlers.computeIfPresent(player.getUniqueId(), (_, packetHandler) -> packetHandler.player == player ? null : packetHandler); } private void injectChannelHandler(Player player) { - if (packetHandlers.containsKey(player.getUniqueId())) - throw new IllegalStateException("A packet handler is already registered for this player"); + var previous = packetHandlers.get(player.getUniqueId()); + if (previous != null) { + if (previous.player == player) + throw new IllegalStateException("A packet handler is already registered for this player"); + removeChannelHandler(previous.channel); // previous session of the same player that has not been removed yet + } var channel = ((CraftPlayer) player).getHandle().connection.connection.channel; var packetHandler = new PacketHandler(player, channel); @@ -113,8 +118,10 @@ private void injectChannelHandler(Player player) { private void removeChannelHandler(Player player) { packetHandlers.remove(player.getUniqueId()); - var channel = ((CraftPlayer) player).getHandle().connection.connection.channel; - + removeChannelHandler(((CraftPlayer) player).getHandle().connection.connection.channel); + } + + private void removeChannelHandler(Channel channel) { try { channel.pipeline().remove(invuiPacketHandlerName); } catch (NoSuchElementException ignored) { diff --git a/invui/src/main/java/xyz/xenondevs/invui/window/WindowManager.java b/invui/src/main/java/xyz/xenondevs/invui/window/WindowManager.java index 4de71f04..6ae92403 100644 --- a/invui/src/main/java/xyz/xenondevs/invui/window/WindowManager.java +++ b/invui/src/main/java/xyz/xenondevs/invui/window/WindowManager.java @@ -82,7 +82,8 @@ public Window getOpenWindow(Player player) { private void handleInventoryClose(InventoryCloseEvent event) { Player player = (Player) event.getPlayer(); AbstractWindow window = (AbstractWindow) getOpenWindow(player); - if (window != null) { + // Player#equals only compares uuids, so this may be the window of a newer session of the same player + if (window != null && window.getViewer() == player) { window.handleClose(event.getReason()); } }