diff --git a/paper-api/src/main/java/org/bukkit/plugin/SimpleServicesManager.java b/paper-api/src/main/java/org/bukkit/plugin/SimpleServicesManager.java index f3dd8490230b..2c2c12ce77a1 100644 --- a/paper-api/src/main/java/org/bukkit/plugin/SimpleServicesManager.java +++ b/paper-api/src/main/java/org/bukkit/plugin/SimpleServicesManager.java @@ -94,7 +94,9 @@ public void unregisterAll(@NotNull Plugin plugin) { it.remove(); } } - } catch (NoSuchElementException e) {} + } catch (NoSuchElementException e) { + // Outer HashMap iterator can throw after inner list removals invalidate its state + } } for (ServiceUnregisterEvent event : unregisteredEvents) { Bukkit.getServer().getPluginManager().callEvent(event); @@ -135,7 +137,8 @@ public void unregister(@NotNull Class service, @NotNull Object provider) { unregisteredEvents.add(new ServiceUnregisterEvent(registered)); } } - } catch (NoSuchElementException e) { // Why does Java suck + } catch (NoSuchElementException e) { + // it2.remove() can corrupt the inner iterator's state on some list implementations } // Get rid of the empty list @@ -143,7 +146,9 @@ public void unregister(@NotNull Class service, @NotNull Object provider) { it.remove(); } } - } catch (NoSuchElementException e) {} + } catch (NoSuchElementException e) { + // Outer HashMap iterator can throw after inner list removals invalidate its state + } } for (ServiceUnregisterEvent event : unregisteredEvents) { Bukkit.getServer().getPluginManager().callEvent(event); @@ -177,7 +182,8 @@ public void unregister(@NotNull Object provider) { unregisteredEvents.add(new ServiceUnregisterEvent(registered)); } } - } catch (NoSuchElementException e) { // Why does Java suck + } catch (NoSuchElementException e) { + // it2.remove() can corrupt the inner iterator's state on some list implementations } // Get rid of the empty list @@ -185,7 +191,9 @@ public void unregister(@NotNull Object provider) { it.remove(); } } - } catch (NoSuchElementException e) {} + } catch (NoSuchElementException e) { + // Outer HashMap iterator can throw after inner list removals invalidate its state + } } for (ServiceUnregisterEvent event : unregisteredEvents) { Bukkit.getServer().getPluginManager().callEvent(event); diff --git a/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java b/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java index d8aae267a038..2417d8829237 100644 --- a/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java +++ b/paper-server/src/main/java/org/bukkit/craftbukkit/inventory/CraftInventoryPlayer.java @@ -164,7 +164,12 @@ public int getHeldItemSlot() { public void setHeldItemSlot(int slot) { Preconditions.checkArgument(slot >= 0 && slot < Inventory.getSelectionSize(), "Slot (%s) is not between 0 and %s inclusive", slot, Inventory.getSelectionSize() - 1); this.getInventory().setSelectedSlot(slot); - ((CraftPlayer) this.getHolder()).getHandle().connection.send(new ClientboundSetHeldSlotPacket(slot)); + // Paper start - Fix NPE when setHeldItemSlot is called on a disconnecting player + if (this.getHolder() == null) return; + ServerPlayer player = ((CraftPlayer) this.getHolder()).getHandle(); + if (player.connection == null) return; + // Paper end - Fix NPE when setHeldItemSlot is called on a disconnecting player + player.connection.send(new ClientboundSetHeldSlotPacket(slot)); } @Override