diff --git a/src/main/java/net/minecraft/world/gen/ChunkProviderServer.java b/src/main/java/net/minecraft/world/gen/ChunkProviderServer.java index 6ddef74..211e5d9 100644 --- a/src/main/java/net/minecraft/world/gen/ChunkProviderServer.java +++ b/src/main/java/net/minecraft/world/gen/ChunkProviderServer.java @@ -50,11 +50,13 @@ import org.ultramine.server.chunk.ChunkMap; import org.ultramine.server.chunk.IChunkLoadCallback; import org.ultramine.server.util.VanillaChunkHashMap; +import org.ultramine.server.util.VanillaChunkHashSet; public class ChunkProviderServer implements IChunkProvider { private static final Logger logger = LogManager.getLogger(); - public IntSet chunksToUnload = HashIntSets.newMutableSet(); + public IntSet unloadQueue = HashIntSets.newMutableSet(); + public Set chunksToUnload = new VanillaChunkHashSet(unloadQueue); //mods compatibility private Chunk defaultEmptyChunk; public IChunkProvider currentChunkProvider; public IChunkLoader currentChunkLoader; @@ -118,7 +120,7 @@ { chunk.unbind(); if(chunk.canUnload()) - chunksToUnload.add(ChunkHash.chunkToKey(par1, par2)); + unloadQueue.add(ChunkHash.chunkToKey(par1, par2)); } } @@ -140,7 +142,7 @@ public Chunk loadChunk(int par1, int par2, Runnable runnable) { - this.chunksToUnload.removeInt(ChunkHash.chunkToKey(par1, par2)); + this.unloadQueue.removeInt(ChunkHash.chunkToKey(par1, par2)); Chunk chunk = chunkMap.get(par1, par2); AnvilChunkLoader loader = null; @@ -184,7 +186,7 @@ public Chunk originalLoadChunk(int par1, int par2) { int k = ChunkHash.chunkToKey(par1, par2); - this.chunksToUnload.removeInt(k); + this.unloadQueue.removeInt(k); Chunk chunk = (Chunk)this.chunkMap.get(par1, par2); if (chunk == null) @@ -392,7 +394,7 @@ Set persistentChunks = worldObj.getPersistentChunks().keySet(); int savequeueSize = ((AnvilChunkLoader)currentChunkLoader).getSaveQueueSize(); - for(IntCursor it = chunksToUnload.cursor(); it.moveNext() && savequeueSize < MAX_SAVE_QUEUE_SIZE;) + for(IntCursor it = unloadQueue.cursor(); it.moveNext() && savequeueSize < MAX_SAVE_QUEUE_SIZE;) { int hash = it.elem(); Chunk chunk = chunkMap.get(hash); @@ -435,7 +437,7 @@ public String makeString() { - return "ServerChunkCache: " + this.chunkMap.size() + " Drop: " + this.chunksToUnload.size(); + return "ServerChunkCache: " + this.chunkMap.size() + " Drop: " + this.unloadQueue.size(); } public List getPossibleCreatures(EnumCreatureType par1EnumCreatureType, int par2, int par3, int par4) @@ -574,7 +576,7 @@ for(IntObjCursor it = chunkMap.iterator(); it.moveNext();) { int key = it.key(); - if(it.value().needsSaving(false) && !chunksToUnload.contains(key)) + if(it.value().needsSaving(false) && !unloadQueue.contains(key)) possibleSaves.add(key); } @@ -590,7 +592,7 @@ int key = it.elem(); it.remove(); Chunk chunk = chunkMap.get(key); - if(chunk != null && chunk.needsSaving(false) && !chunksToUnload.contains(key)) + if(chunk != null && chunk.needsSaving(false) && !unloadQueue.contains(key)) { safeSaveChunk(chunk); chunk.isModified = false; @@ -642,7 +644,7 @@ } chunkMap.clear(); - chunksToUnload.clear(); + unloadQueue.clear(); possibleSaves.clear(); if(!save) ((AnvilChunkLoader)currentChunkLoader).unsafeRemoveAll(); diff --git a/src/main/java/org/ultramine/server/chunk/ChunkGC.java b/src/main/java/org/ultramine/server/chunk/ChunkGC.java index 84a1f15..0cd3197 100644 --- a/src/main/java/org/ultramine/server/chunk/ChunkGC.java +++ b/src/main/java/org/ultramine/server/chunk/ChunkGC.java @@ -43,7 +43,7 @@ int chunkLimit = boundChunks + confCacheSize + MAX_CHUNKS_PER_OP; int curTime = world.func_73046_m().getTickCounter(); - int unloadQueueSize = provider.chunksToUnload.size(); + int unloadQueueSize = provider.unloadQueue.size(); int chunkCount = provider.chunkMap.size() - unloadQueueSize; int timePassed = curTime - lastGCTime; int chunkDiff = chunkCount - lastChunkCount; @@ -62,7 +62,7 @@ for(int i = 0, s = Math.min(unbound.size(), MAX_CHUNKS_PER_OP); i < s; i++) { Chunk chunk = unbound.get(i); - provider.chunksToUnload.add(ChunkHash.chunkToKey(chunk.xPosition, chunk.zPosition)); + provider.unloadQueue.add(ChunkHash.chunkToKey(chunk.xPosition, chunk.zPosition)); } if(unbound.size() - Math.min(unbound.size(), MAX_CHUNKS_PER_OP) > unboundLimit) @@ -76,16 +76,16 @@ } lastGCTime = curTime; - lastChunkCount = provider.chunkMap.size() - provider.chunksToUnload.size(); + lastChunkCount = provider.chunkMap.size() - provider.unloadQueue.size(); } } public void forceCollect() { for(Chunk chunk : findChunksForUnload()) - provider.chunksToUnload.add(ChunkHash.chunkToKey(chunk.xPosition, chunk.zPosition)); + provider.unloadQueue.add(ChunkHash.chunkToKey(chunk.xPosition, chunk.zPosition)); lastGCTime = world.func_73046_m().getTickCounter(); - lastChunkCount = provider.chunkMap.size() - provider.chunksToUnload.size(); + lastChunkCount = provider.chunkMap.size() - provider.unloadQueue.size(); } private List findChunksForUnload() diff --git a/src/main/java/org/ultramine/server/util/VanillaChunkHashSet.java b/src/main/java/org/ultramine/server/util/VanillaChunkHashSet.java new file mode 100644 index 0000000..d0c8c34 --- /dev/null +++ b/src/main/java/org/ultramine/server/util/VanillaChunkHashSet.java @@ -0,0 +1,148 @@ +package org.ultramine.server.util; + +import java.lang.reflect.Array; +import java.util.Collection; +import java.util.Iterator; +import java.util.Set; + +import org.ultramine.server.chunk.ChunkHash; + +import com.google.common.collect.Iterators; + +import net.minecraft.world.ChunkCoordIntPair; +import net.openhft.koloboke.collect.set.IntSet; + +public class VanillaChunkHashSet implements Set +{ + private final IntSet intset; + + public VanillaChunkHashSet(IntSet intset) + { + this.intset = intset; + } + + private static int v2um(long key) + { + return ChunkHash.chunkToKey((int) (key & 0xFFFFFFFFL), (int) (key >>> 32)); + } + + private static long um2v(int key) + { + return ChunkCoordIntPair.chunkXZ2Int(ChunkHash.keyToX(key), ChunkHash.keyToZ(key)); + } + + @Override + public int size() + { + return intset.size(); + } + + @Override + public boolean isEmpty() + { + return intset.isEmpty(); + } + + @Override + public boolean contains(Object o) + { + return o instanceof Long && contains((long)o); + } + + public boolean contains(long l) + { + return intset.contains(v2um(l)); + } + + @Override + @SuppressWarnings("deprecation") + public Iterator iterator() + { + return Iterators.transform(intset.iterator(), (Integer key) -> um2v(key)); + } + + @Override + public Object[] toArray() + { + return toArray(new Long[size()]); + } + + @Override + @SuppressWarnings("unchecked") + public T[] toArray(T[] a) + { + int size = size(); + Long[] r = a.length >= size() ? (Long[]) a : (Long[]) Array.newInstance(a.getClass().getComponentType(), size); + int i = 0; + for(Long l : this) + r[i++] = l; + return (T[]) r; + } + + @Override + public boolean add(Long e) + { + return intset.add(v2um(e)); + } + + @Override + public boolean remove(Object o) + { + return o instanceof Long && remove((long)o); + } + + public boolean remove(long l) + { + return intset.removeInt(v2um(l)); + } + + @Override + public boolean containsAll(Collection c) + { + for(Object o : c) + if(!contains(o)) + return false; + return true; + } + + @Override + public boolean addAll(Collection c) + { + boolean modified = false; + for(Object o : c) + modified |= add((Long)o); + return modified; + } + + @Override + public boolean retainAll(Collection c) + { + boolean modified = false; + for(Iterator it = iterator(); it.hasNext();) + { + Long l = it.next(); + if(!c.contains(l)) + { + it.remove(); + modified = true; + } + } + + return modified; + } + + @Override + public boolean removeAll(Collection c) + { + boolean modified = false; + for(Object o : c) + modified |= remove(o); + return modified; + } + + @Override + public void clear() + { + intset.clear(); + } +}