97 lines
3.0 KiB
Java
97 lines
3.0 KiB
Java
package kcauldron;
|
|
|
|
import java.util.List;
|
|
import java.util.Queue;
|
|
import java.util.concurrent.locks.ReadWriteLock;
|
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
|
|
|
import com.google.common.collect.Lists;
|
|
import com.google.common.collect.Queues;
|
|
|
|
import net.minecraft.server.MinecraftServer;
|
|
import net.minecraft.util.LongHashMap;
|
|
import net.minecraft.world.ChunkCoordIntPair;
|
|
import net.minecraft.world.chunk.Chunk;
|
|
import net.minecraft.world.gen.ChunkProviderServer;
|
|
|
|
public enum ChunkGenerator {
|
|
INSTANCE;
|
|
private final Queue<QueuedChunk> queue = Queues.newArrayDeque();
|
|
private final LongHashMap map = new LongHashMap();
|
|
private final ReadWriteLock lock = new ReentrantReadWriteLock();
|
|
|
|
public void queueChunkGeneration(ChunkProviderServer provider, int cx, int cz, ChunkCallback callback) {
|
|
long key = ChunkCoordIntPair.chunkXZ2Int(cx, cz);
|
|
QueuedChunk chunk;
|
|
lock.readLock().lock();
|
|
try {
|
|
chunk = (QueuedChunk) map.getValueByKey(key);
|
|
} finally {
|
|
lock.readLock().unlock();
|
|
}
|
|
if (chunk != null) {
|
|
chunk.callbacks.add(callback);
|
|
} else {
|
|
chunk = new QueuedChunk(provider, cx, cz, callback);
|
|
lock.writeLock().lock();
|
|
try {
|
|
map.add(key, chunk);
|
|
queue.add(chunk);
|
|
} finally {
|
|
lock.writeLock().unlock();
|
|
}
|
|
}
|
|
}
|
|
|
|
public void chunkGeneratorCycle() {
|
|
int max = MinecraftServer.kcauldronConfig.commonMaxChunkGenPerTick.getValue();
|
|
lock.writeLock().lock();
|
|
try {
|
|
for (int i = 0; i < max && internalGenerate(); i++)
|
|
;
|
|
} finally {
|
|
lock.writeLock().unlock();
|
|
}
|
|
}
|
|
|
|
public boolean generate() {
|
|
lock.writeLock().lock();
|
|
try {
|
|
return internalGenerate();
|
|
} finally {
|
|
lock.writeLock().unlock();
|
|
}
|
|
}
|
|
|
|
private boolean internalGenerate() {
|
|
for (QueuedChunk chunk; (chunk = queue.poll()) != null;) {
|
|
map.remove(ChunkCoordIntPair.chunkXZ2Int(chunk.cx, chunk.cz));
|
|
if (chunk.provider.loadAsync(chunk.cx, chunk.cz, false, chunk))
|
|
continue;
|
|
chunk.onChunkLoaded(chunk.provider.originalLoadChunk(chunk.cx, chunk.cz));
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private static class QueuedChunk implements ChunkCallback {
|
|
public final ChunkProviderServer provider;
|
|
public final int cx;
|
|
public final int cz;
|
|
public final List<ChunkCallback> callbacks = Lists.newArrayListWithCapacity(1);
|
|
|
|
public QueuedChunk(ChunkProviderServer provider, int cx, int cz, ChunkCallback callback) {
|
|
this.provider = provider;
|
|
this.cx = cx;
|
|
this.cz = cz;
|
|
this.callbacks.add(callback);
|
|
}
|
|
|
|
@Override
|
|
public void onChunkLoaded(Chunk chunk) {
|
|
for (ChunkCallback cb : callbacks)
|
|
cb.onChunkLoaded(chunk);
|
|
}
|
|
}
|
|
}
|