From 9760e8f86a8f1ecd25bedd4dcb3680222959f40a Mon Sep 17 00:00:00 2001 From: Spottedleaf Date: Fri, 26 Aug 2022 21:56:55 -0700 Subject: [PATCH] Prevent unloading worlds with pending player logins Logging into an unloaded world isn't going to end well. This may fix the cases of people seeing errors about regionfiles being closed, as loading chunks in an unloaded world will cause this as the regionfile cache is closed but not cleared. --- ...Load-Chunks-for-Login-Asynchronously.patch | 35 +++++++++++++++++++ .../Optimise-nearby-player-lookups.patch | 7 ++-- 2 files changed, 39 insertions(+), 3 deletions(-) diff --git a/patches/server/Load-Chunks-for-Login-Asynchronously.patch b/patches/server/Load-Chunks-for-Login-Asynchronously.patch index 8bab8a55ef..bee4f2a689 100644 --- a/patches/server/Load-Chunks-for-Login-Asynchronously.patch +++ b/patches/server/Load-Chunks-for-Login-Asynchronously.patch @@ -4,6 +4,26 @@ Date: Sun, 19 Apr 2020 04:28:29 -0400 Subject: [PATCH] Load Chunks for Login Asynchronously +diff --git a/src/main/java/net/minecraft/server/level/ServerLevel.java b/src/main/java/net/minecraft/server/level/ServerLevel.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/net/minecraft/server/level/ServerLevel.java ++++ b/src/main/java/net/minecraft/server/level/ServerLevel.java +@@ -0,0 +0,0 @@ import org.bukkit.event.world.GenericGameEvent; + import org.bukkit.event.world.TimeSkipEvent; + // CraftBukkit end + import it.unimi.dsi.fastutil.ints.IntArrayList; // Paper ++import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet; // Paper + + public class ServerLevel extends Level implements WorldGenLevel { + +@@ -0,0 +0,0 @@ public class ServerLevel extends Level implements WorldGenLevel { + return this.getServer().getPlayerList().getPlayer(uuid); + } + // Paper end ++ public final ReferenceOpenHashSet pendingLogin = new ReferenceOpenHashSet<>(); // Paper + + // Add env and gen to constructor, IWorldDataServer -> WorldDataServer + public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, PrimaryLevelData iworlddataserver, ResourceKey resourcekey, LevelStem worlddimension, ChunkProgressListener worldloadlistener, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider) { diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -151,6 +171,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 this.server.invalidateStatus(); + // Paper start - async load spawn in chunk + ServerLevel finalWorldserver = worldserver1; ++ finalWorldserver.pendingLogin.add(player); + int chunkX = loc.getBlockX() >> 4; + int chunkZ = loc.getBlockZ() >> 4; + final net.minecraft.world.level.ChunkPos pos = new net.minecraft.world.level.ChunkPos(chunkX, chunkZ); @@ -171,6 +192,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + player, finalWorldserver, connection, playerconnection, + nbttagcompound, s1, lastKnownName + ); ++ finalWorldserver.pendingLogin.remove(player); + }; + }); + } @@ -252,3 +274,16 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 Iterator iterator = list.iterator(); +diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 +--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java ++++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java +@@ -0,0 +0,0 @@ public final class CraftServer implements Server { + return false; + } + +- if (handle.players().size() > 0) { ++ if (handle.players().size() > 0 || handle.pendingLogin.size() > 0) { // Paper + return false; + } + diff --git a/patches/server/Optimise-nearby-player-lookups.patch b/patches/server/Optimise-nearby-player-lookups.patch index efd7581d63..c02f444590 100644 --- a/patches/server/Optimise-nearby-player-lookups.patch +++ b/patches/server/Optimise-nearby-player-lookups.patch @@ -109,9 +109,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/net/minecraft/server/level/ServerLevel.java +++ b/src/main/java/net/minecraft/server/level/ServerLevel.java @@ -0,0 +0,0 @@ public class ServerLevel extends Level implements WorldGenLevel { - return this.getServer().getPlayerList().getPlayer(uuid); - } // Paper end + public final ReferenceOpenHashSet pendingLogin = new ReferenceOpenHashSet<>(); // Paper + + // Paper start - optimise checkDespawn + public final List playersAffectingSpawning = new java.util.ArrayList<>(); + // Paper end - optimise checkDespawn @@ -189,9 +189,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return ret; + } + // Paper end - optimise get nearest players for entity AI - ++ // Add env and gen to constructor, IWorldDataServer -> WorldDataServer public ServerLevel(MinecraftServer minecraftserver, Executor executor, LevelStorageSource.LevelStorageAccess convertable_conversionsession, PrimaryLevelData iworlddataserver, ResourceKey resourcekey, LevelStem worlddimension, ChunkProgressListener worldloadlistener, boolean flag, long i, List list, boolean flag1, org.bukkit.World.Environment env, org.bukkit.generator.ChunkGenerator gen, org.bukkit.generator.BiomeProvider biomeProvider) { + // Holder holder = worlddimension.typeHolder(); // CraftBukkit - decompile error @@ -0,0 +0,0 @@ public class ServerLevel extends Level implements WorldGenLevel { }