diff --git a/src/main/java/net/minecraft/server/WorldServer.java b/src/main/java/net/minecraft/server/WorldServer.java index 48fdcab53e..b426d5d963 100644 --- a/src/main/java/net/minecraft/server/WorldServer.java +++ b/src/main/java/net/minecraft/server/WorldServer.java @@ -181,6 +181,8 @@ public class WorldServer extends World implements org.bukkit.BlockChangeDelegate this.P.a(this.getTime()); this.methodProfiler.b(); this.V(); + + this.getWorld().processChunkGC(); // CraftBukkit } public BiomeMeta a(EnumCreatureType enumcreaturetype, int i, int j, int k) { diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java index 9642959f44..936cbc64a1 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java @@ -157,6 +157,8 @@ public final class CraftServer implements Server { private int animalSpawn = -1; private int waterAnimalSpawn = -1; private int ambientSpawn = -1; + public int chunkGCPeriod = -1; + public int chunkGCLoadThresh = 0; private File container; private WarningState warningState = WarningState.DEFAULT; private final BooleanWrapper online = new BooleanWrapper(); @@ -202,6 +204,8 @@ public final class CraftServer implements Server { ambientSpawn = configuration.getInt("spawn-limits.ambient"); console.autosavePeriod = configuration.getInt("ticks-per.autosave"); warningState = WarningState.value(configuration.getString("settings.deprecated-verbose")); + chunkGCPeriod = configuration.getInt("chunk-gc.period-in-ticks"); + chunkGCLoadThresh = configuration.getInt("chunk-gc.load-threshold"); updater = new AutoUpdater(new BukkitDLUpdaterService(configuration.getString("auto-updater.host")), getLogger(), configuration.getString("auto-updater.preferred-channel")); updater.setEnabled(configuration.getBoolean("auto-updater.enabled")); @@ -537,6 +541,8 @@ public final class CraftServer implements Server { ambientSpawn = configuration.getInt("spawn-limits.ambient"); warningState = WarningState.value(configuration.getString("settings.deprecated-verbose")); console.autosavePeriod = configuration.getInt("ticks-per.autosave"); + chunkGCPeriod = configuration.getInt("chunk-gc.period-in-ticks"); + chunkGCLoadThresh = configuration.getInt("chunk-gc.load-threshold"); for (WorldServer world : console.worlds) { world.difficulty = difficulty; diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java index b4646d1bf0..cb200667c4 100644 --- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java +++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java @@ -1,6 +1,7 @@ package org.bukkit.craftbukkit; import java.io.File; +import java.util.Iterator; import java.util.Set; import java.util.ArrayList; import java.util.Collection; @@ -58,6 +59,8 @@ public class CraftWorld implements World { private int animalSpawn = -1; private int waterAnimalSpawn = -1; private int ambientSpawn = -1; + private int chunkLoadCount = 0; + private int chunkGCTickCount; private static final Random rand = new Random(); @@ -66,6 +69,10 @@ public class CraftWorld implements World { this.generator = gen; environment = env; + + if (server.chunkGCPeriod > 0) { + chunkGCTickCount = rand.nextInt(server.chunkGCPeriod); + } } public Block getBlockAt(int x, int y, int z) { @@ -226,6 +233,7 @@ public class CraftWorld implements World { } public boolean loadChunk(int x, int z, boolean generate) { + chunkLoadCount++; if (generate) { // Use the default variant of loadChunk when generate == true. return world.chunkProviderServer.getChunkAt(x, z) != null; @@ -1233,4 +1241,34 @@ public class CraftWorld implements World { public boolean isGameRule(String rule) { return getHandle().getGameRules().e(rule); } + + public void processChunkGC() { + chunkGCTickCount++; + + if (chunkLoadCount >= server.chunkGCLoadThresh && server.chunkGCLoadThresh > 0) { + chunkLoadCount = 0; + } else if (chunkGCTickCount >= server.chunkGCPeriod && server.chunkGCPeriod > 0) { + chunkGCTickCount = 0; + } else { + return; + } + + ChunkProviderServer cps = world.chunkProviderServer; + Iterator iter = cps.chunks.values().iterator(); + while (iter.hasNext()) { + net.minecraft.server.Chunk chunk = iter.next(); + // If in use, skip it + if (isChunkInUse(chunk.x, chunk.z)) { + continue; + } + + // Already unloading? + if (cps.unloadQueue.contains(chunk.x, chunk.z)) { + continue; + } + + // Add unload request + cps.queueUnload(chunk.x, chunk.z); + } + } } diff --git a/src/main/resources/configurations/bukkit.yml b/src/main/resources/configurations/bukkit.yml index e4d6d96fe6..61a95e3373 100644 --- a/src/main/resources/configurations/bukkit.yml +++ b/src/main/resources/configurations/bukkit.yml @@ -30,6 +30,9 @@ spawn-limits: animals: 15 water-animals: 5 ambient: 15 +chunk-gc: + period-in-ticks: 600 + load-threshold: 0 ticks-per: animal-spawns: 400 monster-spawns: 1