You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
555 lines
24 KiB
555 lines
24 KiB
--- ../src-base/minecraft/net/minecraft/world/gen/ChunkProviderServer.java |
|
+++ ../src-work/minecraft/net/minecraft/world/gen/ChunkProviderServer.java |
|
@@ -1,7 +1,13 @@ |
|
package net.minecraft.world.gen; |
|
|
|
import com.google.common.collect.Lists; |
|
+ |
|
import cpw.mods.fml.common.registry.GameRegistry; |
|
+import gnu.trove.impl.sync.TSynchronizedLongObjectMap; |
|
+import gnu.trove.map.TLongObjectMap; |
|
+import gnu.trove.map.hash.TLongObjectHashMap; |
|
+import gnu.trove.procedure.TObjectProcedure; |
|
+ |
|
import java.io.IOException; |
|
import java.util.ArrayList; |
|
import java.util.Collections; |
|
@@ -9,6 +15,7 @@ |
|
import java.util.List; |
|
import java.util.Set; |
|
import java.util.concurrent.ConcurrentHashMap; |
|
+ |
|
import net.minecraft.crash.CrashReport; |
|
import net.minecraft.crash.CrashReportCategory; |
|
import net.minecraft.entity.EnumCreatureType; |
|
@@ -33,22 +40,52 @@ |
|
import org.apache.logging.log4j.LogManager; |
|
import org.apache.logging.log4j.Logger; |
|
|
|
+ |
|
+ |
|
+ |
|
+ |
|
+// CraftBukkit start |
|
+import java.util.Random; |
|
+ |
|
+import net.minecraft.block.BlockSand; |
|
+ |
|
+import org.bukkit.Server; |
|
+import org.bukkit.craftbukkit.util.LongHash; |
|
+import org.bukkit.craftbukkit.util.LongHashSet; |
|
+import org.bukkit.craftbukkit.util.LongObjectHashMap; |
|
+import org.bukkit.event.world.ChunkUnloadEvent; |
|
+ |
|
+ |
|
+ |
|
+ |
|
+ |
|
+// CraftBukkit end |
|
+// Cauldron start |
|
+import cpw.mods.fml.common.FMLCommonHandler; |
|
+import net.minecraft.server.MinecraftServer; |
|
+import net.minecraftforge.cauldron.configuration.CauldronConfig; |
|
+import net.minecraftforge.cauldron.CauldronHooks; |
|
+// Cauldron end |
|
+ |
|
public class ChunkProviderServer implements IChunkProvider |
|
{ |
|
private static final Logger logger = LogManager.getLogger(); |
|
- private Set chunksToUnload = Collections.newSetFromMap(new ConcurrentHashMap()); |
|
- private Chunk defaultEmptyChunk; |
|
+ public LongHashSet chunksToUnload = new LongHashSet(); // LongHashSet |
|
+ public Chunk defaultEmptyChunk; |
|
public IChunkProvider currentChunkProvider; |
|
public IChunkLoader currentChunkLoader; |
|
- public boolean loadChunkOnProvideRequest = true; |
|
- public LongHashMap loadedChunkHashMap = new LongHashMap(); |
|
- public List loadedChunks = new ArrayList(); |
|
+ public boolean loadChunkOnProvideRequest = MinecraftServer.getServer().cauldronConfig.loadChunkOnRequest.getValue(); // Cauldron - if true, allows mods to force load chunks. to disable, set load-chunk-on-request in cauldron.yml to false |
|
+ public int initialTick; // Cauldron counter to keep track of when this loader was created |
|
+ public TLongObjectMap<Chunk> loadedChunkHashMap_KC = new TSynchronizedLongObjectMap<Chunk>(new TLongObjectHashMap<Chunk>()); public ConcurrentHashMap<Integer,Chunk> chunkt_KC = new ConcurrentHashMap<Integer,Chunk>(); |
|
+ public List loadedChunks = new ArrayList(); // Cauldron - vanilla compatibility |
|
public WorldServer worldObj; |
|
private Set<Long> loadingChunks = com.google.common.collect.Sets.newHashSet(); |
|
+ public LongHashMap loadedChunkHashMap = new kcauldron.wrapper.VanillaChunkHashMap(loadedChunkHashMap_KC); // KCauldron - vanilla/mystcraft compatibility |
|
private static final String __OBFID = "CL_00001436"; |
|
|
|
public ChunkProviderServer(WorldServer p_i1520_1_, IChunkLoader p_i1520_2_, IChunkProvider p_i1520_3_) |
|
{ |
|
+ this.initialTick = MinecraftServer.currentTick; // Cauldron keep track of when the loader was created |
|
this.defaultEmptyChunk = new EmptyChunk(p_i1520_1_, 0, 0); |
|
this.worldObj = p_i1520_1_; |
|
this.currentChunkLoader = p_i1520_2_; |
|
@@ -57,16 +94,22 @@ |
|
|
|
public boolean chunkExists(int p_73149_1_, int p_73149_2_) |
|
{ |
|
- return this.loadedChunkHashMap.containsItem(ChunkCoordIntPair.chunkXZ2Int(p_73149_1_, p_73149_2_)); |
|
+ return this.chunkt_KC.containsKey(chunk_hash(p_73149_1_, p_73149_2_)); //KCauldron Replacement |
|
} |
|
|
|
- public List func_152380_a() |
|
+ public List func_152380_a() // Vanilla compatibility |
|
{ |
|
return this.loadedChunks; |
|
} |
|
|
|
public void unloadChunksIfNotNearSpawn(int p_73241_1_, int p_73241_2_) |
|
{ |
|
+ // PaperSpigot start - Asynchronous lighting updates |
|
+ Chunk chunk = this.chunkt_KC.get(chunk_hash(p_73241_1_, p_73241_2_)); //KCauldron replacement |
|
+ if (chunk != null && chunk.worldObj.spigotConfig.useAsyncLighting && (chunk.pendingLightUpdates.get() > 0 || chunk.worldObj.getTotalWorldTime() - chunk.lightUpdateTime < 20)) { |
|
+ return; |
|
+ } |
|
+ // PaperSpigot end |
|
if (this.worldObj.provider.canRespawnHere() && DimensionManager.shouldLoadSpawn(this.worldObj.provider.dimensionId)) |
|
{ |
|
ChunkCoordinates chunkcoordinates = this.worldObj.getSpawnPoint(); |
|
@@ -74,26 +117,49 @@ |
|
int l = p_73241_2_ * 16 + 8 - chunkcoordinates.posZ; |
|
short short1 = 128; |
|
|
|
+ // CraftBukkit start |
|
if (k < -short1 || k > short1 || l < -short1 || l > short1) |
|
{ |
|
- this.chunksToUnload.add(Long.valueOf(ChunkCoordIntPair.chunkXZ2Int(p_73241_1_, p_73241_2_))); |
|
+ this.chunksToUnload.add(p_73241_1_, p_73241_2_); |
|
+ Chunk c = this.chunkt_KC.get(chunk_hash(p_73241_1_, p_73241_2_)); //KCauldron replacement |
|
+ |
|
+ if (c != null) |
|
+ { |
|
+ c.mustSave = true; |
|
+ } |
|
+ CauldronHooks.logChunkUnload(this, p_73241_1_, p_73241_2_, "Chunk added to unload queue"); |
|
} |
|
+ |
|
+ // CraftBukkit end |
|
} |
|
else |
|
{ |
|
- this.chunksToUnload.add(Long.valueOf(ChunkCoordIntPair.chunkXZ2Int(p_73241_1_, p_73241_2_))); |
|
+ // CraftBukkit start |
|
+ this.chunksToUnload.add(p_73241_1_, p_73241_2_); |
|
+ Chunk c = this.chunkt_KC.get(chunk_hash(p_73241_1_, p_73241_2_)); //KCauldron replacement |
|
+ |
|
+ if (c != null) |
|
+ { |
|
+ c.mustSave = true; |
|
+ } |
|
+ CauldronHooks.logChunkUnload(this, p_73241_1_, p_73241_2_, "Chunk added to unload queue"); |
|
+ // CraftBukkit end |
|
} |
|
} |
|
|
|
public void unloadAllChunks() |
|
{ |
|
- Iterator iterator = this.loadedChunks.iterator(); |
|
+ this.loadedChunkHashMap_KC.forEachValue(new TObjectProcedure<Chunk>() { |
|
+ @Override |
|
+ public boolean execute(Chunk chunk) { |
|
+ unloadChunksIfNotNearSpawn(chunk.xPosition, chunk.zPosition); |
|
+ return true; |
|
+ } |
|
+ }); |
|
+ } |
|
|
|
- while (iterator.hasNext()) |
|
- { |
|
- Chunk chunk = (Chunk)iterator.next(); |
|
- this.unloadChunksIfNotNearSpawn(chunk.xPosition, chunk.zPosition); |
|
- } |
|
+ public Chunk getChunkIfLoaded(int x, int z) { |
|
+ return this.chunkt_KC.get(chunk_hash(x,z)); //KCauldron replacement |
|
} |
|
|
|
public Chunk loadChunk(int p_73158_1_, int p_73158_2_) |
|
@@ -103,9 +169,9 @@ |
|
|
|
public Chunk loadChunk(int par1, int par2, Runnable runnable) |
|
{ |
|
- long k = ChunkCoordIntPair.chunkXZ2Int(par1, par2); |
|
- this.chunksToUnload.remove(Long.valueOf(k)); |
|
- Chunk chunk = (Chunk)this.loadedChunkHashMap.getValueByKey(k); |
|
+ this.chunksToUnload.remove(par1, par2); |
|
+ Chunk chunk = (Chunk) this.chunkt_KC.get(chunk_hash(par1,par2)); //KCauldron replacement |
|
+ boolean newChunk = false; |
|
AnvilChunkLoader loader = null; |
|
|
|
if (this.currentChunkLoader instanceof AnvilChunkLoader) |
|
@@ -113,6 +179,8 @@ |
|
loader = (AnvilChunkLoader) this.currentChunkLoader; |
|
} |
|
|
|
+ CauldronHooks.logChunkLoad(this, "Get", par1, par2, true); |
|
+ |
|
// We can only use the queue for already generated chunks |
|
if (chunk == null && loader != null && loader.chunkExists(this.worldObj, par1, par2)) |
|
{ |
|
@@ -142,18 +210,19 @@ |
|
|
|
public Chunk originalLoadChunk(int p_73158_1_, int p_73158_2_) |
|
{ |
|
- long k = ChunkCoordIntPair.chunkXZ2Int(p_73158_1_, p_73158_2_); |
|
- this.chunksToUnload.remove(Long.valueOf(k)); |
|
- Chunk chunk = (Chunk)this.loadedChunkHashMap.getValueByKey(k); |
|
+ this.chunksToUnload.remove(p_73158_1_, p_73158_2_); |
|
+ Chunk chunk = (Chunk) this.chunkt_KC.get(chunk_hash(p_73158_1_, p_73158_2_)); //KCauldron replacement |
|
+ boolean newChunk = false; // CraftBukkit |
|
|
|
if (chunk == null) |
|
{ |
|
- boolean added = loadingChunks.add(k); |
|
+ worldObj.timings.syncChunkLoadTimer.startTiming(); // Spigot |
|
+ boolean added = loadingChunks.add(LongHash.toLong(p_73158_1_, p_73158_2_)); |
|
if (!added) |
|
{ |
|
cpw.mods.fml.common.FMLLog.bigWarning("There is an attempt to load a chunk (%d,%d) in dimension %d that is already being loaded. This will cause weird chunk breakages.", p_73158_1_, p_73158_2_, worldObj.provider.dimensionId); |
|
} |
|
- chunk = ForgeChunkManager.fetchDormantChunk(k, this.worldObj); |
|
+ chunk = ForgeChunkManager.fetchDormantChunk(LongHash.toLong(p_73158_1_, p_73158_2_), this.worldObj); |
|
if (chunk == null) |
|
{ |
|
chunk = this.safeLoadChunk(p_73158_1_, p_73158_2_); |
|
@@ -176,18 +245,53 @@ |
|
CrashReport crashreport = CrashReport.makeCrashReport(throwable, "Exception generating new chunk"); |
|
CrashReportCategory crashreportcategory = crashreport.makeCategory("Chunk to be generated"); |
|
crashreportcategory.addCrashSection("Location", String.format("%d,%d", new Object[] {Integer.valueOf(p_73158_1_), Integer.valueOf(p_73158_2_)})); |
|
- crashreportcategory.addCrashSection("Position hash", Long.valueOf(k)); |
|
+ crashreportcategory.addCrashSection("Position hash", LongHash.toLong(p_73158_1_, p_73158_2_)); |
|
crashreportcategory.addCrashSection("Generator", this.currentChunkProvider.makeString()); |
|
throw new ReportedException(crashreport); |
|
} |
|
} |
|
+ |
|
+ newChunk = true; // CraftBukkit |
|
} |
|
|
|
- this.loadedChunkHashMap.add(k, chunk); |
|
- this.loadedChunks.add(chunk); |
|
- loadingChunks.remove(k); |
|
- chunk.onChunkLoad(); |
|
+ this.loadedChunkHashMap_KC.put(LongHash.toLong(p_73158_1_, p_73158_2_), chunk); this.chunkt_KC.put(chunk_hash(p_73158_1_, p_73158_2_), chunk); //KCauldron - IntHash |
|
+ this.loadedChunks.add(chunk); // Cauldron - vanilla compatibility |
|
+ loadingChunks.remove(LongHash.toLong(p_73158_1_, p_73158_2_)); // Cauldron - LongHash |
|
+ |
|
+ if (chunk != null) |
|
+ { |
|
+ chunk.onChunkLoad(); |
|
+ } |
|
+ // CraftBukkit start |
|
+ Server server = this.worldObj.getServer(); |
|
+ |
|
+ if (server != null) |
|
+ { |
|
+ /* |
|
+ * If it's a new world, the first few chunks are generated inside |
|
+ * the World constructor. We can't reliably alter that, so we have |
|
+ * no way of creating a CraftWorld/CraftServer at that point. |
|
+ */ |
|
+ server.getPluginManager().callEvent(new org.bukkit.event.world.ChunkLoadEvent(chunk.bukkitChunk, newChunk)); |
|
+ } |
|
+ |
|
+ // Update neighbor counts |
|
+ for (int x = -2; x < 3; x++) { |
|
+ for (int z = -2; z < 3; z++) { |
|
+ if (x == 0 && z == 0) { |
|
+ continue; |
|
+ } |
|
+ |
|
+ Chunk neighbor = this.getChunkIfLoaded(chunk.xPosition + x, chunk.zPosition + z); |
|
+ if (neighbor != null) { |
|
+ neighbor.setNeighborLoaded(-x, -z); |
|
+ chunk.setNeighborLoaded(x, z); |
|
+ } |
|
+ } |
|
+ } |
|
+ // CraftBukkit end |
|
chunk.populateChunk(this, this, p_73158_1_, p_73158_2_); |
|
+ worldObj.timings.syncChunkLoadTimer.stopTiming(); // Spigot |
|
} |
|
|
|
return chunk; |
|
@@ -195,11 +299,29 @@ |
|
|
|
public Chunk provideChunk(int p_73154_1_, int p_73154_2_) |
|
{ |
|
- Chunk chunk = (Chunk)this.loadedChunkHashMap.getValueByKey(ChunkCoordIntPair.chunkXZ2Int(p_73154_1_, p_73154_2_)); |
|
- return chunk == null ? (!this.worldObj.findingSpawnPoint && !this.loadChunkOnProvideRequest ? this.defaultEmptyChunk : this.loadChunk(p_73154_1_, p_73154_2_)) : chunk; |
|
+ // CraftBukkit start |
|
+ Chunk chunk = (Chunk) this.chunkt_KC.get(chunk_hash(p_73154_1_, p_73154_2_)); //KCauldron replacement |
|
+ chunk = chunk == null ? (shouldLoadChunk() ? this.loadChunk(p_73154_1_, p_73154_2_) : this.defaultEmptyChunk) : chunk; // Cauldron handle forge server tick events and load the chunk within 5 seconds of the world being loaded (for chunk loaders) |
|
+ |
|
+ if (chunk == this.defaultEmptyChunk) |
|
+ { |
|
+ return chunk; |
|
+ } |
|
+ |
|
+ if ((p_73154_1_ != chunk.xPosition || p_73154_2_ != chunk.zPosition) && !worldObj.isProfilingWorld()) |
|
+ { |
|
+ logger.error("Chunk (" + chunk.xPosition + ", " + chunk.zPosition + ") stored at (" + p_73154_1_ + ", " + p_73154_2_ + ") in world '" + worldObj.getWorld().getName() + "'"); |
|
+ logger.error(chunk.getClass().getName()); |
|
+ Throwable ex = new Throwable(); |
|
+ ex.fillInStackTrace(); |
|
+ ex.printStackTrace(); |
|
+ } |
|
+ chunk.lastAccessedTick = MinecraftServer.getServer().getTickCounter(); // Cauldron |
|
+ return chunk; |
|
+ // CraftBukkit end |
|
} |
|
|
|
- private Chunk safeLoadChunk(int p_73239_1_, int p_73239_2_) |
|
+ public Chunk safeLoadChunk(int p_73239_1_, int p_73239_2_) // CraftBukkit - private -> public |
|
{ |
|
if (this.currentChunkLoader == null) |
|
{ |
|
@@ -209,6 +331,7 @@ |
|
{ |
|
try |
|
{ |
|
+ CauldronHooks.logChunkLoad(this, "Safe Load", p_73239_1_, p_73239_2_, false); // Cauldron |
|
Chunk chunk = this.currentChunkLoader.loadChunk(this.worldObj, p_73239_1_, p_73239_2_); |
|
|
|
if (chunk != null) |
|
@@ -217,8 +340,11 @@ |
|
|
|
if (this.currentChunkProvider != null) |
|
{ |
|
+ worldObj.timings.syncChunkLoadStructuresTimer.startTiming(); // Spigot |
|
this.currentChunkProvider.recreateStructures(p_73239_1_, p_73239_2_); |
|
+ worldObj.timings.syncChunkLoadStructuresTimer.stopTiming(); // Spigot |
|
} |
|
+ chunk.lastAccessedTick = MinecraftServer.getServer().getTickCounter(); // Cauldron |
|
} |
|
|
|
return chunk; |
|
@@ -231,7 +357,7 @@ |
|
} |
|
} |
|
|
|
- private void safeSaveExtraChunkData(Chunk p_73243_1_) |
|
+ public void safeSaveExtraChunkData(Chunk p_73243_1_) // CraftBukkit - private -> public |
|
{ |
|
if (this.currentChunkLoader != null) |
|
{ |
|
@@ -246,7 +372,7 @@ |
|
} |
|
} |
|
|
|
- private void safeSaveChunk(Chunk p_73242_1_) |
|
+ public void safeSaveChunk(Chunk p_73242_1_) // CraftBukkit - private -> public |
|
{ |
|
if (this.currentChunkLoader != null) |
|
{ |
|
@@ -254,15 +380,18 @@ |
|
{ |
|
p_73242_1_.lastSaveTime = this.worldObj.getTotalWorldTime(); |
|
this.currentChunkLoader.saveChunk(this.worldObj, p_73242_1_); |
|
+ // CraftBukkit start - IOException to Exception |
|
} |
|
- catch (IOException ioexception) |
|
+ catch (Exception ioexception) |
|
{ |
|
logger.error("Couldn\'t save chunk", ioexception); |
|
} |
|
+ /* Remove extra exception |
|
catch (MinecraftException minecraftexception) |
|
{ |
|
logger.error("Couldn\'t save chunk; already in use by another instance of Minecraft?", minecraftexception); |
|
} |
|
+ // CraftBukkit end */ |
|
} |
|
} |
|
|
|
@@ -277,6 +406,35 @@ |
|
if (this.currentChunkProvider != null) |
|
{ |
|
this.currentChunkProvider.populate(p_73153_1_, p_73153_2_, p_73153_3_); |
|
+ // CraftBukkit start |
|
+ BlockSand.fallInstantly = true; |
|
+ Random random = new Random(); |
|
+ random.setSeed(worldObj.getSeed()); |
|
+ long xRand = random.nextLong() / 2L * 2L + 1L; |
|
+ long zRand = random.nextLong() / 2L * 2L + 1L; |
|
+ random.setSeed((long) p_73153_2_ * xRand + (long) p_73153_3_ * zRand ^ worldObj.getSeed()); |
|
+ org.bukkit.World world = this.worldObj.getWorld(); |
|
+ |
|
+ if (world != null) |
|
+ { |
|
+ this.worldObj.populating = true; |
|
+ |
|
+ try |
|
+ { |
|
+ for (org.bukkit.generator.BlockPopulator populator : world.getPopulators()) |
|
+ { |
|
+ populator.populate(world, random, chunk.bukkitChunk); |
|
+ } |
|
+ } |
|
+ finally |
|
+ { |
|
+ this.worldObj.populating = false; |
|
+ } |
|
+ } |
|
+ |
|
+ BlockSand.fallInstantly = false; |
|
+ this.worldObj.getServer().getPluginManager().callEvent(new org.bukkit.event.world.ChunkPopulateEvent(chunk.bukkitChunk)); |
|
+ // CraftBukkit end |
|
GameRegistry.generateWorld(p_73153_2_, p_73153_3_, worldObj, currentChunkProvider, p_73153_1_); |
|
chunk.setChunkModified(); |
|
} |
|
@@ -286,11 +444,13 @@ |
|
public boolean saveChunks(boolean p_73151_1_, IProgressUpdate p_73151_2_) |
|
{ |
|
int i = 0; |
|
- ArrayList arraylist = Lists.newArrayList(this.loadedChunks); |
|
+ // Cauldron start - use thread-safe method for iterating loaded chunks |
|
+ Object[] chunks = this.loadedChunks.toArray(); |
|
|
|
- for (int j = 0; j < arraylist.size(); ++j) |
|
+ for (int j = 0; j < chunks.length; ++j) |
|
{ |
|
- Chunk chunk = (Chunk)arraylist.get(j); |
|
+ Chunk chunk = (Chunk)chunks[j]; |
|
+ //Cauldron end |
|
|
|
if (p_73151_1_) |
|
{ |
|
@@ -325,36 +485,73 @@ |
|
{ |
|
if (!this.worldObj.levelSaving) |
|
{ |
|
- for (ChunkCoordIntPair forced : this.worldObj.getPersistentChunks().keySet()) |
|
+ // Cauldron start - remove any chunk that has a ticket associated with it |
|
+ if (!this.chunksToUnload.isEmpty()) |
|
{ |
|
- this.chunksToUnload.remove(ChunkCoordIntPair.chunkXZ2Int(forced.chunkXPos, forced.chunkZPos)); |
|
+ for (ChunkCoordIntPair forcedChunk : this.worldObj.getPersistentChunks().keys()) |
|
+ { |
|
+ this.chunksToUnload.remove(forcedChunk.chunkXPos, forcedChunk.chunkZPos); |
|
+ } |
|
} |
|
+ // Cauldron end |
|
+ // CraftBukkit start |
|
+ Server server = this.worldObj.getServer(); |
|
|
|
- for (int i = 0; i < 100; ++i) |
|
+ for (int i = 0; i < 100 && !this.chunksToUnload.isEmpty(); i++) |
|
{ |
|
- if (!this.chunksToUnload.isEmpty()) |
|
+ long chunkcoordinates = this.chunksToUnload.popFirst(); |
|
+ Chunk chunk = this.loadedChunkHashMap_KC.get(chunkcoordinates); //Not using the IntMap for this |
|
+ |
|
+ if (chunk == null) |
|
{ |
|
- Long olong = (Long)this.chunksToUnload.iterator().next(); |
|
- Chunk chunk = (Chunk)this.loadedChunkHashMap.getValueByKey(olong.longValue()); |
|
+ continue; |
|
+ } |
|
|
|
- if (chunk != null) |
|
- { |
|
- chunk.onChunkUnload(); |
|
- this.safeSaveChunk(chunk); |
|
- this.safeSaveExtraChunkData(chunk); |
|
- this.loadedChunks.remove(chunk); |
|
- ForgeChunkManager.putDormantChunk(ChunkCoordIntPair.chunkXZ2Int(chunk.xPosition, chunk.zPosition), chunk); |
|
- if(loadedChunks.size() == 0 && ForgeChunkManager.getPersistentChunksFor(this.worldObj).size() == 0 && !DimensionManager.shouldLoadSpawn(this.worldObj.provider.dimensionId)){ |
|
- DimensionManager.unloadWorld(this.worldObj.provider.dimensionId); |
|
- return currentChunkProvider.unloadQueuedChunks(); |
|
+ // Cauldron static - check if the chunk was accessed recently and keep it loaded if there are players in world |
|
+ if (!shouldUnloadChunk(chunk) && this.worldObj.playerEntities.size() > 0) |
|
+ { |
|
+ CauldronHooks.logChunkUnload(this, chunk.xPosition, chunk.zPosition, "** Chunk kept from unloading due to recent activity"); |
|
+ continue; |
|
+ } |
|
+ // Cauldron end |
|
+ |
|
+ |
|
+ ChunkUnloadEvent event = new ChunkUnloadEvent(chunk.bukkitChunk); |
|
+ server.getPluginManager().callEvent(event); |
|
+ |
|
+ if (!event.isCancelled()) |
|
+ { |
|
+ CauldronHooks.logChunkUnload(this, chunk.xPosition, chunk.zPosition, "Unloading Chunk at"); |
|
+ |
|
+ chunk.onChunkUnload(); |
|
+ this.safeSaveChunk(chunk); |
|
+ this.safeSaveExtraChunkData(chunk); |
|
+ // Update neighbor counts |
|
+ for (int x = -2; x < 3; x++) { |
|
+ for (int z = -2; z < 3; z++) { |
|
+ if (x == 0 && z == 0) { |
|
+ continue; |
|
+ } |
|
+ |
|
+ Chunk neighbor = this.getChunkIfLoaded(chunk.xPosition + x, chunk.zPosition + z); |
|
+ if (neighbor != null) { |
|
+ neighbor.setNeighborUnloaded(-x, -z); |
|
+ chunk.setNeighborUnloaded(x, z); |
|
+ } |
|
} |
|
} |
|
- |
|
- this.chunksToUnload.remove(olong); |
|
- this.loadedChunkHashMap.remove(olong.longValue()); |
|
+ this.loadedChunkHashMap_KC.remove(chunkcoordinates); // CraftBukkit |
|
+ this.loadedChunks.remove(chunk); this.chunkt_KC.remove(chunk_hash(chunk.xPosition,chunk.zPosition)); //KCauldron - IntHashMap |
|
+ ForgeChunkManager.putDormantChunk(chunkcoordinates, chunk); |
|
+ if(this.loadedChunkHashMap_KC.size() == 0 && ForgeChunkManager.getPersistentChunksFor(this.worldObj).size() == 0 && !DimensionManager.shouldLoadSpawn(this.worldObj.provider.dimensionId)){ |
|
+ DimensionManager.unloadWorld(this.worldObj.provider.dimensionId); |
|
+ return currentChunkProvider.unloadQueuedChunks(); |
|
+ } |
|
} |
|
} |
|
|
|
+ // CraftBukkit end |
|
+ |
|
if (this.currentChunkLoader != null) |
|
{ |
|
this.currentChunkLoader.chunkTick(); |
|
@@ -371,7 +568,7 @@ |
|
|
|
public String makeString() |
|
{ |
|
- return "ServerChunkCache: " + this.loadedChunkHashMap.getNumHashElements() + " Drop: " + this.chunksToUnload.size(); |
|
+ return "ServerChunkCache: " + this.loadedChunkHashMap_KC.size() + " Drop: " + this.chunksToUnload.size(); // Cauldron |
|
} |
|
|
|
public List getPossibleCreatures(EnumCreatureType p_73155_1_, int p_73155_2_, int p_73155_3_, int p_73155_4_) |
|
@@ -386,8 +583,31 @@ |
|
|
|
public int getLoadedChunkCount() |
|
{ |
|
- return this.loadedChunkHashMap.getNumHashElements(); |
|
+ return this.loadedChunkHashMap_KC.size(); // Cauldron |
|
} |
|
|
|
public void recreateStructures(int p_82695_1_, int p_82695_2_) {} |
|
+ |
|
+ // Cauldron start |
|
+ private boolean shouldLoadChunk() |
|
+ { |
|
+ return this.worldObj.findingSpawnPoint || |
|
+ this.loadChunkOnProvideRequest || |
|
+ (MinecraftServer.callingForgeTick && MinecraftServer.getServer().cauldronConfig.loadChunkOnForgeTick.getValue()) || |
|
+ (MinecraftServer.currentTick - initialTick <= 100); |
|
+ } |
|
+ |
|
+ public long lastAccessed(int x, int z) |
|
+ { |
|
+ int chunkHash = chunk_hash(x,z); |
|
+ if (!chunkt_KC.containsKey(chunkHash)) return 0; |
|
+ return chunkt_KC.get(chunkHash).lastAccessedTick; |
|
+ } |
|
+ |
|
+ private boolean shouldUnloadChunk(Chunk chunk) |
|
+ { |
|
+ if (chunk == null) return false; |
|
+ return MinecraftServer.getServer().getTickCounter() - chunk.lastAccessedTick > MinecraftServer.getServer().cauldronConfig.chunkGCGracePeriod.getValue(); |
|
+ } |
|
+ |
|
+ public static int chunk_hash(int x, int y) |
|
+ { |
|
+ return ((x & 0xFFFF) << 16) | (y & 0xFFFF); |
|
+ } |
|
+ // Cauldron end |
|
}
|
|
|