1
0
forked from xjboss/KCauldronX

Finally fix #67

This commit is contained in:
Prototik 2015-06-27 16:32:21 +07:00
parent 9fdf330495
commit 8c50b9899f
19 changed files with 737 additions and 704 deletions

View File

@ -73,7 +73,7 @@
if (this.players.isEmpty())
{
+ if (this.theWorldServer.loadedEntityList.size() == 0 || this.theWorldServer.theChunkProviderServer.loadedChunkHashMap.size() == 0)
+ if (this.theWorldServer.loadedEntityList.size() == 0 || this.theWorldServer.theChunkProviderServer.loadedChunkHashMap_KC.size() == 0)
+ {
+ return; // CraftBukkit - Only do unload when we go from non-empty to empty
+ }

View File

@ -67,11 +67,11 @@
- 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 = new TSynchronizedLongObjectMap<Chunk>(new TLongObjectHashMap<Chunk>());
+ public TLongObjectMap<Chunk> loadedChunkHashMap_KC = new TSynchronizedLongObjectMap<Chunk>(new TLongObjectHashMap<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_vanilla = new LongHashMap(); // Cauldron - vanilla/mystcraft compatibility
+ 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_)
@ -85,7 +85,7 @@
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.loadedChunkHashMap.containsKey(LongHash.toLong(p_73149_1_, p_73149_2_)); // CraftBukkit
+ return this.loadedChunkHashMap_KC.containsKey(LongHash.toLong(p_73149_1_, p_73149_2_)); // CraftBukkit
}
- public List func_152380_a()
@ -102,7 +102,7 @@
{
- 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.loadedChunkHashMap.get(LongHash.toLong(p_73241_1_, p_73241_2_));
+ Chunk c = this.loadedChunkHashMap_KC.get(LongHash.toLong(p_73241_1_, p_73241_2_));
+
+ if (c != null)
+ {
@ -118,7 +118,7 @@
- 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.loadedChunkHashMap.get(LongHash.toLong(p_73241_1_, p_73241_2_));
+ Chunk c = this.loadedChunkHashMap_KC.get(LongHash.toLong(p_73241_1_, p_73241_2_));
+
+ if (c != null)
+ {
@ -138,7 +138,7 @@
- Chunk chunk = (Chunk)iterator.next();
- this.unloadChunksIfNotNearSpawn(chunk.xPosition, chunk.zPosition);
- }
+ this.loadedChunkHashMap.forEachValue(new TObjectProcedure<Chunk>() {
+ this.loadedChunkHashMap_KC.forEachValue(new TObjectProcedure<Chunk>() {
+ @Override
+ public boolean execute(Chunk chunk) {
+ unloadChunksIfNotNearSpawn(chunk.xPosition, chunk.zPosition);
@ -156,7 +156,7 @@
- this.chunksToUnload.remove(Long.valueOf(k));
- Chunk chunk = (Chunk)this.loadedChunkHashMap.getValueByKey(k);
+ this.chunksToUnload.remove(par1, par2);
+ Chunk chunk = (Chunk) this.loadedChunkHashMap.get(LongHash.toLong(par1, par2));
+ Chunk chunk = (Chunk) this.loadedChunkHashMap_KC.get(LongHash.toLong(par1, par2));
+ boolean newChunk = false;
AnvilChunkLoader loader = null;
@ -178,7 +178,7 @@
- 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.loadedChunkHashMap.get(LongHash.toLong(p_73158_1_, p_73158_2_));
+ Chunk chunk = (Chunk) this.loadedChunkHashMap_KC.get(LongHash.toLong(p_73158_1_, p_73158_2_));
+ boolean newChunk = false; // CraftBukkit
if (chunk == null)
@ -195,7 +195,7 @@
if (chunk == null)
{
chunk = this.safeLoadChunk(p_73158_1_, p_73158_2_);
@@ -176,18 +235,40 @@
@@ -176,18 +235,39 @@
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_)}));
@ -213,9 +213,8 @@
- this.loadedChunks.add(chunk);
- loadingChunks.remove(k);
- chunk.onChunkLoad();
+ this.loadedChunkHashMap.put(LongHash.toLong(p_73158_1_, p_73158_2_), chunk); // CraftBukkit
+ this.loadedChunkHashMap_KC.put(LongHash.toLong(p_73158_1_, p_73158_2_), chunk); // CraftBukkit
+ this.loadedChunks.add(chunk); // Cauldron - vanilla compatibility
+ this.loadedChunkHashMap_vanilla.add(ChunkCoordIntPair.chunkXZ2Int(p_73158_1_, p_73158_2_), chunk); // Cauldron - vanilla/mystcraft compatibility
+ loadingChunks.remove(LongHash.toLong(p_73158_1_, p_73158_2_)); // Cauldron - LongHash
+
+ if (chunk != null)
@ -241,14 +240,14 @@
}
return chunk;
@@ -195,11 +276,29 @@
@@ -195,11 +275,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.loadedChunkHashMap.get(LongHash.toLong(p_73154_1_, p_73154_2_));
+ Chunk chunk = (Chunk) this.loadedChunkHashMap_KC.get(LongHash.toLong(p_73154_1_, p_73154_2_));
+ 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)
@ -274,7 +273,7 @@
{
if (this.currentChunkLoader == null)
{
@@ -209,6 +308,7 @@
@@ -209,6 +307,7 @@
{
try
{
@ -282,7 +281,7 @@
Chunk chunk = this.currentChunkLoader.loadChunk(this.worldObj, p_73239_1_, p_73239_2_);
if (chunk != null)
@@ -217,8 +317,11 @@
@@ -217,8 +316,11 @@
if (this.currentChunkProvider != null)
{
@ -294,7 +293,7 @@
}
return chunk;
@@ -231,7 +334,7 @@
@@ -231,7 +333,7 @@
}
}
@ -303,7 +302,7 @@
{
if (this.currentChunkLoader != null)
{
@@ -246,7 +349,7 @@
@@ -246,7 +348,7 @@
}
}
@ -312,7 +311,7 @@
{
if (this.currentChunkLoader != null)
{
@@ -254,15 +357,18 @@
@@ -254,15 +356,18 @@
{
p_73242_1_.lastSaveTime = this.worldObj.getTotalWorldTime();
this.currentChunkLoader.saveChunk(this.worldObj, p_73242_1_);
@ -332,7 +331,7 @@
}
}
@@ -277,6 +383,35 @@
@@ -277,6 +382,35 @@
if (this.currentChunkProvider != null)
{
this.currentChunkProvider.populate(p_73153_1_, p_73153_2_, p_73153_3_);
@ -368,7 +367,7 @@
GameRegistry.generateWorld(p_73153_2_, p_73153_3_, worldObj, currentChunkProvider, p_73153_1_);
chunk.setChunkModified();
}
@@ -286,11 +421,13 @@
@@ -286,11 +420,13 @@
public boolean saveChunks(boolean p_73151_1_, IProgressUpdate p_73151_2_)
{
int i = 0;
@ -385,7 +384,7 @@
if (p_73151_1_)
{
@@ -325,36 +462,61 @@
@@ -325,36 +461,60 @@
{
if (!this.worldObj.levelSaving)
{
@ -408,7 +407,7 @@
{
- if (!this.chunksToUnload.isEmpty())
+ long chunkcoordinates = this.chunksToUnload.popFirst();
+ Chunk chunk = this.loadedChunkHashMap.get(chunkcoordinates);
+ Chunk chunk = this.loadedChunkHashMap_KC.get(chunkcoordinates);
+
+ if (chunk == null)
{
@ -451,11 +450,10 @@
+ this.safeSaveChunk(chunk);
+ this.safeSaveExtraChunkData(chunk);
+ // this.unloadQueue.remove(olong);
+ this.loadedChunkHashMap.remove(chunkcoordinates); // CraftBukkit
+ this.loadedChunkHashMap_KC.remove(chunkcoordinates); // CraftBukkit
+ this.loadedChunks.remove(chunk); // Cauldron - vanilla compatibility
+ this.loadedChunkHashMap_vanilla.remove(ChunkCoordIntPair.chunkXZ2Int(LongHash.msw(chunkcoordinates), LongHash.lsw(chunkcoordinates))); // Cauldron - vanilla/mystcraft compatibility
+ ForgeChunkManager.putDormantChunk(chunkcoordinates, chunk);
+ if(this.loadedChunkHashMap.size() == 0 && ForgeChunkManager.getPersistentChunksFor(this.worldObj).size() == 0 && !DimensionManager.shouldLoadSpawn(this.worldObj.provider.dimensionId)){
+ 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();
+ }
@ -467,21 +465,21 @@
if (this.currentChunkLoader != null)
{
this.currentChunkLoader.chunkTick();
@@ -371,7 +533,7 @@
@@ -371,7 +531,7 @@
public String makeString()
{
- return "ServerChunkCache: " + this.loadedChunkHashMap.getNumHashElements() + " Drop: " + this.chunksToUnload.size();
+ return "ServerChunkCache: " + this.loadedChunkHashMap.size() + " Drop: " + this.chunksToUnload.size(); // Cauldron
+ 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 +548,31 @@
@@ -386,8 +546,31 @@
public int getLoadedChunkCount()
{
- return this.loadedChunkHashMap.getNumHashElements();
+ return this.loadedChunkHashMap.size(); // Cauldron
+ return this.loadedChunkHashMap_KC.size(); // Cauldron
}
public void recreateStructures(int p_82695_1_, int p_82695_2_) {}
@ -498,8 +496,8 @@
+ public long lastAccessed(int x, int z)
+ {
+ long chunkHash = LongHash.toLong(x, z);
+ if (!loadedChunkHashMap.containsKey(chunkHash)) return 0;
+ return loadedChunkHashMap.get(chunkHash).lastAccessedTick;
+ if (!loadedChunkHashMap_KC.containsKey(chunkHash)) return 0;
+ return loadedChunkHashMap_KC.get(chunkHash).lastAccessedTick;
+ }
+
+ /*private boolean shouldUnloadChunk(Chunk chunk)

View File

@ -10,14 +10,13 @@
class ChunkIOProvider implements AsynchronousExecutor.CallBackProvider<QueuedChunk, net.minecraft.world.chunk.Chunk, Runnable, RuntimeException> {
private final AtomicInteger threadNumber = new AtomicInteger(1);
@@ -41,13 +44,21 @@
@@ -41,13 +44,20 @@
queuedChunk.loader.loadEntities(queuedChunk.world, queuedChunk.compound.getCompoundTag("Level"), chunk);
MinecraftForge.EVENT_BUS.post(new ChunkDataEvent.Load(chunk, queuedChunk.compound)); // Don't call ChunkDataEvent.Load async
chunk.lastSaveTime = queuedChunk.provider.worldObj.getTotalWorldTime();
- queuedChunk.provider.loadedChunkHashMap.add(ChunkCoordIntPair.chunkXZ2Int(queuedChunk.x, queuedChunk.z), chunk);
+ queuedChunk.provider.loadedChunkHashMap.put(LongHash.toLong(queuedChunk.x, queuedChunk.z), chunk);
+ queuedChunk.provider.loadedChunkHashMap_KC.put(LongHash.toLong(queuedChunk.x, queuedChunk.z), chunk);
queuedChunk.provider.loadedChunks.add(chunk);
+ queuedChunk.provider.loadedChunkHashMap_vanilla.add(ChunkCoordIntPair.chunkXZ2Int(queuedChunk.x, queuedChunk.z), chunk); // Cauldron - vanilla/mystcraft compatibility
chunk.onChunkLoad();
if (queuedChunk.provider.currentChunkProvider != null) {

View File

@ -1,13 +1,10 @@
package kcauldron;
import static org.objectweb.asm.Opcodes.*;
import static org.objectweb.asm.Opcodes.ALOAD;
import static org.objectweb.asm.Opcodes.ARETURN;
import static org.objectweb.asm.Opcodes.GETFIELD;
import org.apache.logging.log4j.Level;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.tree.FieldInsnNode;
import org.objectweb.asm.tree.InsnList;
import org.objectweb.asm.tree.InsnNode;
@ -21,42 +18,6 @@ import cpw.mods.fml.common.FMLLog;
public class KCauldronClassTransformer implements Transformer {
@Override
public void transform(final ImagineASM asm) {
if (asm.is("net.minecraft.world.gen.ChunkProviderServer")
|| asm.is("net.minecraftforge.common.chunkio.ChunkIOProvider")
|| asm.is("org.bukkit.craftbukkit.CraftWorld")
|| asm.is("org.bukkit.craftbukkit.v1_7_R4.CraftWorld")) {
FMLLog.log(Level.INFO, "KCauldron: Patching " + asm.getActualName() + " for compatibility with Mystcraft");
ClassReader reader = new ClassReader(asm.build());
ClassWriter writer = new ClassWriter(ClassWriter.COMPUTE_MAXS);
reader.accept(new ClassVisitor(ASM5, writer) {
@Override
public FieldVisitor visitField(int access, String name,
String desc, String signature, Object value) {
if ("loadedChunkHashMap_vanilla".equals(name)) {
name = asm.isDev() ? "loadedChunkHashMap" : "field_73244_f";
}
return super.visitField(access, name, desc, signature,
value);
}
@Override
public MethodVisitor visitMethod(int access, String name,
String desc, String signature, String[] exceptions) {
return new MethodVisitor(api, super.visitMethod(access,
name, desc, signature, exceptions)) {
@Override
public void visitFieldInsn(int opcode, String owner,
String name, String desc) {
if ("loadedChunkHashMap_vanilla".equals(name)) {
name = asm.isDev() ? "loadedChunkHashMap" : "field_73244_f";
}
super.visitFieldInsn(opcode, owner, name, desc);
}
};
}
}, 0);
asm.loadClass(writer.toByteArray());
}
if (asm.is("climateControl.utils.ChunkGeneratorExtractor")) {
boolean undergroundBiomesInstalled = false;
try {

View File

@ -0,0 +1,40 @@
package kcauldron.wrapper;
import gnu.trove.map.TLongObjectMap;
import net.minecraft.util.LongHashMap;
public class LongHashMapTrove<T> extends LongHashMap {
private final TLongObjectMap<T> mMap;
public LongHashMapTrove(TLongObjectMap<T> map) {
mMap = map;
}
@SuppressWarnings("unchecked")
@Override
public void add(long key, Object value) {
mMap.put(key, (T) value);
}
@Override
public int getNumHashElements() {
return mMap.size();
}
@Override
public Object getValueByKey(long key) {
return mMap.get(key);
}
@Override
public boolean containsItem(long key) {
return mMap.containsKey(key);
}
@Override
public Object remove(long key) {
return mMap.remove(key);
}
}

View File

@ -0,0 +1,36 @@
package kcauldron.wrapper;
import gnu.trove.map.TLongObjectMap;
import net.minecraft.world.chunk.Chunk;
import org.bukkit.craftbukkit.util.LongHash;
public class VanillaChunkHashMap extends LongHashMapTrove<Chunk> {
public VanillaChunkHashMap(TLongObjectMap<Chunk> map) {
super(map);
}
private static long V2B(long key) {
return LongHash.toLong((int) (key & 0xFFFFFFFFL), (int) (key >>> 32));
}
@Override
public void add(long key, Object value) {
super.add(V2B(key), value);
}
@Override
public boolean containsItem(long key) {
return super.containsItem(V2B(key));
}
@Override
public Object getValueByKey(long key) {
return super.getValueByKey(V2B(key));
}
@Override
public Object remove(long key) {
return super.remove(V2B(key));
}
}

View File

@ -332,7 +332,7 @@ public class CauldronHooks
writer.name("name").value(world.getWorld().getName());
writer.name("dimensionId").value(world.provider.dimensionId);
writer.name("players").value(world.playerEntities.size());
writer.name("loadedChunks").value(world.theChunkProviderServer.loadedChunkHashMap.size());
writer.name("loadedChunks").value(world.theChunkProviderServer.loadedChunkHashMap_KC.size());
writer.name("activeChunks").value(world.activeChunkSet.size());
writer.name("entities").value(world.loadedEntityList.size());
writer.name("tiles").value(world.loadedTileEntityList.size());

View File

@ -110,7 +110,7 @@ public class CauldronCommand extends Command
for (net.minecraft.world.WorldServer world : MinecraftServer.getServer().worlds)
{
sender.sendMessage(ChatColor.GOLD + "Dimension: " + ChatColor.GRAY + world.provider.dimensionId +
ChatColor.GOLD + " Loaded Chunks: " + ChatColor.GRAY + world.theChunkProviderServer.loadedChunkHashMap.size() +
ChatColor.GOLD + " Loaded Chunks: " + ChatColor.GRAY + world.theChunkProviderServer.loadedChunkHashMap_KC.size() +
ChatColor.GOLD + " Active Chunks: " + ChatColor.GRAY + world.activeChunkSet.size() +
ChatColor.GOLD + " Entities: " + ChatColor.GRAY + world.loadedEntityList.size() +
ChatColor.GOLD + " Tile Entities: " + ChatColor.GRAY + world.loadedTileEntityList.size()

View File

@ -138,7 +138,7 @@ public class CraftWorld implements World {
}
public Chunk[] getLoadedChunks() {
Object[] chunks = world.theChunkProviderServer.loadedChunkHashMap.values();
Object[] chunks = world.theChunkProviderServer.loadedChunkHashMap_KC.values();
org.bukkit.Chunk[] craftChunks = new CraftChunk[chunks.length];
for (int i = 0; i < chunks.length; i++) {
@ -262,7 +262,7 @@ public class CraftWorld implements World {
}
world.theChunkProviderServer.chunksToUnload.remove(x, z);
net.minecraft.world.chunk.Chunk chunk = world.theChunkProviderServer.loadedChunkHashMap.get(LongHash.toLong(x, z));
net.minecraft.world.chunk.Chunk chunk = world.theChunkProviderServer.loadedChunkHashMap_KC.get(LongHash.toLong(x, z));
if (chunk == null) {
world.timings.syncChunkLoadTimer.startTiming(); // Spigot
@ -276,9 +276,8 @@ public class CraftWorld implements World {
private void chunkLoadPostProcess(net.minecraft.world.chunk.Chunk chunk, int x, int z) {
if (chunk != null) {
world.theChunkProviderServer.loadedChunkHashMap.put(LongHash.toLong(x, z), chunk);
world.theChunkProviderServer.loadedChunkHashMap_KC.put(LongHash.toLong(x, z), chunk);
world.theChunkProviderServer.loadedChunks.add(chunk); // Cauldron - vanilla compatibility
world.theChunkProviderServer.loadedChunkHashMap_vanilla.add(ChunkCoordIntPair.chunkXZ2Int(x, z), chunk);
chunk.onChunkLoad();
@ -1395,7 +1394,7 @@ public class CraftWorld implements World {
}
final net.minecraft.world.gen.ChunkProviderServer cps = world.theChunkProviderServer;
cps.loadedChunkHashMap.forEachValue(new TObjectProcedure<net.minecraft.world.chunk.Chunk>() {
cps.loadedChunkHashMap_KC.forEachValue(new TObjectProcedure<net.minecraft.world.chunk.Chunk>() {
@Override
public boolean execute(net.minecraft.world.chunk.Chunk chunk) {
// If in use, skip it

View File

@ -89,7 +89,7 @@ public class WatchdogThread extends Thread
{
log.log(Level.SEVERE, " Dimension:" + world.provider.dimensionId);
log.log(Level.SEVERE,
" Loaded Chunks: " + world.theChunkProviderServer.loadedChunkHashMap.size() + " Active Chunks: " + world.activeChunkSet.size()
" Loaded Chunks: " + world.theChunkProviderServer.loadedChunkHashMap_KC.size() + " Active Chunks: " + world.activeChunkSet.size()
+ " Entities: " + world.loadedEntityList.size() + " Tile Entities: " + world.loadedTileEntityList.size());
log.log(Level.SEVERE, " Entities Last Tick: " + world.entitiesTicked);
log.log(Level.SEVERE, " Tiles Last Tick: " + world.tilesTicked);
@ -153,7 +153,7 @@ public class WatchdogThread extends Thread
for (net.minecraft.world.WorldServer world : MinecraftServer.getServer().worlds)
{
log.log(Level.WARNING, " Dimension:" + world.provider.dimensionId);
log.log(Level.WARNING, " Loaded Chunks: " + world.theChunkProviderServer.loadedChunkHashMap.size() +
log.log(Level.WARNING, " Loaded Chunks: " + world.theChunkProviderServer.loadedChunkHashMap_KC.size() +
" Active Chunks: " + world.activeChunkSet.size() +
" Entities: " + world.loadedEntityList.size() +
" Tile Entities: " + world.loadedTileEntityList.size());