--- a/net/minecraft/server/level/DistanceManager.java +++ b/net/minecraft/server/level/DistanceManager.java @@ -72,6 +_,12 @@ } if (!this.chunksToUpdateFutures.isEmpty()) { + // CraftBukkit start - SPIGOT-7780: Call chunk unload events before updateHighestAllowedStatus + for (final ChunkHolder chunkHolder : this.chunksToUpdateFutures) { + chunkHolder.callEventIfUnloading(chunkMap); + } + // CraftBukkit end - SPIGOT-7780: Call chunk unload events before updateHighestAllowedStatus + for (ChunkHolder chunkHolder : this.chunksToUpdateFutures) { chunkHolder.updateHighestAllowedStatus(chunkMap); } @@ -121,8 +_,10 @@ ChunkPos chunkPos = sectionPos.chunk(); long packedChunkPos = chunkPos.toLong(); ObjectSet set = this.playersPerChunk.get(packedChunkPos); - set.remove(player); - if (set.isEmpty()) { + // Paper start - some state corruption happens here, don't crash, clean up gracefully + if (set != null) set.remove(player); + if (set == null || set.isEmpty()) { + // Paper end - some state corruption happens here, don't crash, clean up gracefully this.playersPerChunk.remove(packedChunkPos); this.naturalSpawnChunkCounter.update(packedChunkPos, Integer.MAX_VALUE, false); this.playerTicketManager.update(packedChunkPos, Integer.MAX_VALUE, false);