package net.minecraftforge.common.chunkio;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.storage.AnvilChunkLoader;
import net.minecraft.world.gen.ChunkProviderServer;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.math.ChunkPos;
import org.spongepowered.common.SpongeImpl; // Sponge
import org.spongepowered.server.world.chunkio.AsyncAnvilChunkLoader; // Sponge
//import net.minecraftforge.common.MinecraftForge; // Sponge
//import net.minecraftforge.event.world.ChunkDataEvent; // Sponge
import java.io.IOException;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.function.Consumer;
class ChunkIOProvider implements Runnable
{
private final QueuedChunk chunkInfo;
private final AnvilChunkLoader loader;
private final ChunkProviderServer provider;
private Chunk chunk;
private NBTTagCompound nbt;
private final ConcurrentLinkedQueue<Consumer<Chunk>> callbacks = new ConcurrentLinkedQueue<>(); // Sponge: Runnable -> Consumer<Chunk>
private boolean ran = false;
ChunkIOProvider(QueuedChunk chunk, AnvilChunkLoader loader, ChunkProviderServer provider)
{
this.chunkInfo = chunk;
this.loader = loader;
this.provider = provider;
}
public void addCallback(Consumer<Chunk> callback) // Sponge: Runnable -> Consumer<Chunk>
{
this.callbacks.add(callback);
}
public void removeCallback(Consumer<Chunk> callback) // Sponge: Runnable -> Consumer<Chunk>
{
this.callbacks.remove(callback);
}
@Override
public void run() // async stuff
{
synchronized(this)
{
//Object[] data = null; // Sponge
try
{
// Sponge start: Use Sponge's async chunk load method
//data = this.loader.loadChunk__Async(chunkInfo.world, chunkInfo.x, chunkInfo.z);
this.nbt = AsyncAnvilChunkLoader.read(this.loader, this.chunkInfo.x, this.chunkInfo.z);
if (this.nbt != null) {
this.chunk = this.loader.checkedReadChunkFromNBT(this.chunkInfo.world, this.chunkInfo.x, this.chunkInfo.z, this.nbt);
}
// Sponge end
}
catch (IOException e)
{
// Sponge: Use Sponge logging
//e.printStackTrace();
SpongeImpl.getLogger().error("Could not load chunk in {} @ ({}, {})", this.chunkInfo.world, this.chunkInfo.x, this.chunkInfo.z, e);
}
// Sponge start: data is not used
/*if (data != null)
{
this.nbt = (NBTTagCompound)data[1];
this.chunk = (Chunk)data[0];
}*/
// Sponge end
this.ran = true;
this.notifyAll();
}
}
// sync stuff
public void syncCallback()
{
if (chunk == null)
{
this.runCallbacks();
return;
}
// Load Entities
// Sponge: Use Sponge's loadEntities method
//this.loader.loadEntities(this.chunkInfo.world, this.nbt.getCompoundTag("Level"), this.chunk);
AsyncAnvilChunkLoader.loadEntities(this.chunkInfo.world, this.chunk, this.nbt);
// Sponge: Don't call Forge event
//MinecraftForge.EVENT_BUS.post(new ChunkDataEvent.Load(this.chunk, this.nbt)); // Don't call ChunkDataEvent.Load async
this.chunk.setLastSaveTime(provider.world.getTotalWorldTime());
this.provider.chunkGenerator.recreateStructures(this.chunk, this.chunkInfo.x, this.chunkInfo.z);
provider.id2ChunkMap.put(ChunkPos.asLong(this.chunkInfo.x, this.chunkInfo.z), this.chunk);
this.chunk.onChunkLoad();
this.chunk.populateChunk(provider, provider.chunkGenerator);
this.runCallbacks();
}
public Chunk getChunk()
{
return this.chunk;
}
public boolean runFinished()
{
return this.ran;
}
public boolean hasCallback()
{
return this.callbacks.size() > 0;
}
public void runCallbacks()
{
for (Consumer<Chunk> r : this.callbacks) // Sponge: Runnable -> Consumer<Chunk>
{
// Sponge: Pass chunk argument
//r.run();
r.accept(this.chunk);
}
this.callbacks.clear();
}
}