From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Aikar Date: Fri, 8 May 2020 20:30:58 -0400 Subject: [PATCH] Fix CraftServer.unloadWorld Leak The dimension manager was still registered which leaked the entire World diff --git a/src/main/java/net/minecraft/server/DimensionManager.java b/src/main/java/net/minecraft/server/DimensionManager.java index 5724fe6e57d3671b4978aecaf217ac4c2e0d7f82..3af9709a8717b1d9c445c3b04163027177a81711 100644 --- a/src/main/java/net/minecraft/server/DimensionManager.java +++ b/src/main/java/net/minecraft/server/DimensionManager.java @@ -20,6 +20,14 @@ public class DimensionManager implements MinecraftSerializable { private final boolean hasSkyLight; private final GenLayerZoomer genLayerZoomer; + // Paper start + public static void unregister(String s, DimensionManager dimensionmanager) { + MinecraftServer.getServer().execute(() -> { + RegistryMaterials registry = (RegistryMaterials) IRegistry.DIMENSION_TYPE; + registry.deleteValue(new MinecraftKey(s), dimensionmanager); + }); + } + // Paper end public static DimensionManager register(String s, DimensionManager dimensionmanager) { return (DimensionManager) IRegistry.a(IRegistry.DIMENSION_TYPE, dimensionmanager.id, s, dimensionmanager); } diff --git a/src/main/java/net/minecraft/server/RegistryID.java b/src/main/java/net/minecraft/server/RegistryID.java index e8a48b9a4c999281869dfb85577c2b44d6e30eb7..5335e7acc85f0fe9699e5ed59e5aaae5f381347d 100644 --- a/src/main/java/net/minecraft/server/RegistryID.java +++ b/src/main/java/net/minecraft/server/RegistryID.java @@ -9,12 +9,26 @@ import javax.annotation.Nullable; public class RegistryID implements Registry { private static final Object a = null; - private K[] b; + private K[] b; // Paper - diff below private int[] c; - private K[] d; + private K[] d; // Paper - diff below private int e; private int f; private java.util.BitSet usedIds; // Paper + // Paper start + public void removeValue(K value) { + removeValue(value, this.b); + removeValue(value, this.d); + rehash(this.b.length); + } + public void removeValue(K value, K[] arr) { + for (int i = 0; i < arr.length; i++) { + K k = arr[i]; + if (k == value) { + arr[i] = null; + } + } + } public RegistryID(int i) { i = (int) ((float) i / 0.8F); @@ -58,6 +72,7 @@ public class RegistryID implements Registry { return this.e; } + private void rehash(int i) { d(i); } // Paper - OBFHELPER private void d(int i) { K[] ak = this.b; int[] aint = this.c; diff --git a/src/main/java/net/minecraft/server/RegistryMaterials.java b/src/main/java/net/minecraft/server/RegistryMaterials.java index 8477febca23b575da21023b4d7c18bb679cf3b30..dcdd8d38dee89ae7ac404a431e51a61c50b6d45c 100644 --- a/src/main/java/net/minecraft/server/RegistryMaterials.java +++ b/src/main/java/net/minecraft/server/RegistryMaterials.java @@ -22,18 +22,23 @@ public class RegistryMaterials extends IRegistryWritable { private int V; public RegistryMaterials() {} + public T deleteValue(MinecraftKey minecraftkey, T value) { + this.b.removeValue(value); // Diff 1 + this.d = null; // Diff 2 + return this.c.remove(minecraftkey); // Diff 3 + } @Override public V a(int i, MinecraftKey minecraftkey, V v0) { - this.b.a(v0, i); + this.b.a(v0, i); // Paper - diff above 1 Validate.notNull(minecraftkey); Validate.notNull(v0); - this.d = null; + this.d = null; // Diff 2 if (this.c.containsKey(minecraftkey)) { RegistryMaterials.LOGGER.debug("Adding duplicate key '{}' to registry", minecraftkey); } - this.c.put(minecraftkey, v0); + this.c.put(minecraftkey, v0); // Paper - diff3 if (this.V <= i) { this.V = i + 1; } diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java index b89f99a66fe2ab9ad4c956c38c9e4b1d79716c9c..c2b7cb36052455eef2100a1924dc76a5921fa858 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -60,6 +60,7 @@ import net.minecraft.server.EntityPlayer; import net.minecraft.server.EnumDifficulty; import net.minecraft.server.EnumGamemode; import net.minecraft.server.IRecipe; +import net.minecraft.server.IRegistry; import net.minecraft.server.Item; import net.minecraft.server.ItemWorldMap; import net.minecraft.server.Items; @@ -1099,7 +1100,11 @@ public final class CraftServer implements Server { } worlds.remove(world.getName().toLowerCase(java.util.Locale.ENGLISH)); - console.worldServer.remove(handle.getWorldProvider().getDimensionManager()); + // Paper start + DimensionManager dimensionManager = handle.getWorldProvider().getDimensionManager(); + DimensionManager.unregister(world.getName().toLowerCase(java.util.Locale.ENGLISH), dimensionManager); + console.worldServer.remove(dimensionManager); + // Paper end return true; }