package org.bukkit.craftbukkit.chunkio;
import java.io.IOException;
import co.aikar.timings.Timing;
import net.minecraft.server.Chunk;
import net.minecraft.server.ChunkCoordIntPair;
import net.minecraft.server.ChunkRegionLoader;
import net.minecraft.server.NBTTagCompound;
import org.bukkit.Server;
import org.bukkit.craftbukkit.util.AsynchronousExecutor;
import java.util.concurrent.atomic.AtomicInteger;
class ChunkIOProvider implements AsynchronousExecutor.CallBackProvider<QueuedChunk, Chunk, Runnable, RuntimeException> {
private final AtomicInteger threadNumber = new AtomicInteger(1);
// async stuff
public Chunk callStage1(QueuedChunk queuedChunk) throws RuntimeException {
try (Timing ignored = queuedChunk.provider.world.timings.chunkIOStage1.startTimingIfSync()) { // Paper
ChunkRegionLoader loader = queuedChunk.loader;
Object[] data = loader.loadChunk(queuedChunk.world, queuedChunk.x, queuedChunk.z);
if (data != null) {
queuedChunk.compound = (NBTTagCompound) data[1];
return (Chunk) data[0];
}
return null;
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
// sync stuff
public void callStage2(QueuedChunk queuedChunk, Chunk chunk) throws RuntimeException {
if (chunk == null || queuedChunk.provider.chunks.containsKey(ChunkCoordIntPair.a(queuedChunk.x, queuedChunk.z))) { // Paper - also call original if it was already loaded
// If the chunk loading failed (or was already loaded for some reason) just do it synchronously (may generate)
queuedChunk.provider.originalGetChunkAt(queuedChunk.x, queuedChunk.z);
return;
}
try (Timing ignored = queuedChunk.provider.world.timings.chunkIOStage2.startTimingIfSync()) { // Paper
queuedChunk.loader.loadEntities(chunk, queuedChunk.compound.getCompound("Level"), queuedChunk.world);
chunk.setLastSaved(queuedChunk.provider.world.getTime());
queuedChunk.provider.chunks.put(ChunkCoordIntPair.a(queuedChunk.x, queuedChunk.z), chunk);
chunk.addEntities();
if (queuedChunk.provider.chunkGenerator != null) {
queuedChunk.provider.chunkGenerator.recreateStructures(chunk, queuedChunk.x, queuedChunk.z);
}
chunk.loadNearby(queuedChunk.provider, queuedChunk.provider.chunkGenerator, false);
} // Paper
}
public void callStage3(QueuedChunk queuedChunk, Chunk chunk, Runnable runnable) throws RuntimeException {
runnable.run();
}
public Thread newThread(Runnable runnable) {
Thread thread = new Thread(runnable, "Chunk I/O Executor Thread-" + threadNumber.getAndIncrement());
thread.setDaemon(true);
return thread;
}
}