package mekanism.common.tile.component;
import io.netty.buffer.ByteBuf;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
import mekanism.api.Coord4D;
import mekanism.api.MekanismConfig.general;
import mekanism.common.Mekanism;
import mekanism.common.Upgrade;
import mekanism.common.base.ITileComponent;
import mekanism.common.base.IUpgradeTile;
import mekanism.common.chunkloading.IChunkLoader;
import mekanism.common.tile.TileEntityContainerBlock;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.util.math.ChunkPos;
import net.minecraftforge.common.ForgeChunkManager;
import net.minecraftforge.common.ForgeChunkManager.Ticket;
import net.minecraftforge.common.ForgeChunkManager.Type;
import net.minecraftforge.common.util.Constants.NBT;
public class TileComponentChunkLoader implements ITileComponent
{
/** TileEntity implementing this component. */
public TileEntityContainerBlock tileEntity;
public Ticket chunkTicket;
public Set<ChunkPos> chunkSet = new HashSet<ChunkPos>();
public Coord4D prevCoord;
public TileComponentChunkLoader(TileEntityContainerBlock tile)
{
tileEntity = tile;
tile.components.add(this);
}
public void setTicket(Ticket t)
{
if(chunkTicket != t && chunkTicket != null && chunkTicket.world == tileEntity.getWorld())
{
for(ChunkPos chunk : chunkTicket.getChunkList())
{
if(ForgeChunkManager.getPersistentChunksFor(tileEntity.getWorld()).keys().contains(chunk))
{
ForgeChunkManager.unforceChunk(chunkTicket, chunk);
}
}
ForgeChunkManager.releaseTicket(chunkTicket);
}
chunkTicket = t;
}
public void release()
{
setTicket(null);
}
public void sortChunks()
{
if(chunkTicket != null)
{
for(ChunkPos chunk : chunkTicket.getChunkList())
{
if(!chunkSet.contains(chunk))
{
if(ForgeChunkManager.getPersistentChunksFor(tileEntity.getWorld()).keys().contains(chunk))
{
ForgeChunkManager.unforceChunk(chunkTicket, chunk);
}
}
}
for(ChunkPos chunk : chunkSet)
{
if(!chunkTicket.getChunkList().contains(chunk))
{
ForgeChunkManager.forceChunk(chunkTicket, chunk);
}
}
}
}
public void refreshChunkSet()
{
IChunkLoader loader = (IChunkLoader)tileEntity;
if(!chunkSet.equals(loader.getChunkSet()))
{
chunkSet = loader.getChunkSet();
sortChunks();
}
}
public void forceChunks(Ticket ticket)
{
setTicket(ticket);
for(ChunkPos chunk : chunkSet)
{
ForgeChunkManager.forceChunk(chunkTicket, chunk);
}
}
public boolean canOperate()
{
return general.allowChunkloading && ((IUpgradeTile)tileEntity).getComponent().getInstalledTypes().contains(Upgrade.ANCHOR);
}
@Override
public void tick()
{
if(!tileEntity.getWorld().isRemote)
{
if(prevCoord == null || !prevCoord.equals(Coord4D.get(tileEntity)))
{
release();
prevCoord = Coord4D.get(tileEntity);
}
if(chunkTicket != null && (!canOperate() || chunkTicket.world != tileEntity.getWorld()))
{
release();
}
refreshChunkSet();
if(canOperate() && chunkTicket == null)
{
Ticket ticket = ForgeChunkManager.requestTicket(Mekanism.instance, tileEntity.getWorld(), Type.NORMAL);
if(ticket != null)
{
ticket.getModData().setInteger("xCoord", tileEntity.getPos().getX());
ticket.getModData().setInteger("yCoord", tileEntity.getPos().getY());
ticket.getModData().setInteger("zCoord", tileEntity.getPos().getZ());
forceChunks(ticket);
}
}
}
}
@Override
public void read(NBTTagCompound nbtTags)
{
prevCoord = Coord4D.read(nbtTags.getCompoundTag("prevCoord"));
chunkSet.clear();
NBTTagList list = nbtTags.getTagList("chunkSet", NBT.TAG_COMPOUND);
for(int i = 0; i < list.tagCount(); i++)
{
NBTTagCompound compound = list.getCompoundTagAt(i);
chunkSet.add(new ChunkPos(compound.getInteger("chunkX"), compound.getInteger("chunkZ")));
}
}
@Override
public void read(ByteBuf dataStream) {}
@Override
public void write(NBTTagCompound nbtTags)
{
if(prevCoord != null)
{
nbtTags.setTag("prevCoord", prevCoord.write(new NBTTagCompound()));
}
NBTTagList list = new NBTTagList();
for(ChunkPos pos : chunkSet)
{
NBTTagCompound compound = new NBTTagCompound();
compound.setInteger("chunkX", pos.chunkXPos);
compound.setInteger("chunkZ", pos.chunkZPos);
list.appendTag(compound);
}
nbtTags.setTag("chunkSet", list);
}
@Override
public void write(ArrayList<Object> data) {}
@Override
public void invalidate()
{
if(!tileEntity.getWorld().isRemote)
{
release();
}
}
}