package blusunrize.immersiveengineering.common.blocks.metal;
import blusunrize.immersiveengineering.api.Lib;
import blusunrize.immersiveengineering.api.crafting.RefineryRecipe;
import blusunrize.immersiveengineering.common.blocks.IEBlockInterfaces.IAdvancedCollisionBounds;
import blusunrize.immersiveengineering.common.blocks.IEBlockInterfaces.IAdvancedSelectionBounds;
import blusunrize.immersiveengineering.common.blocks.IEBlockInterfaces.IGuiTile;
import blusunrize.immersiveengineering.common.blocks.multiblocks.MultiblockRefinery;
import blusunrize.immersiveengineering.common.util.Utils;
import com.google.common.collect.Lists;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.FluidTank;
import net.minecraftforge.fluids.FluidUtil;
import net.minecraftforge.fluids.IFluidTank;
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.oredict.OreDictionary;
import java.util.ArrayList;
import java.util.List;
public class TileEntityRefinery extends TileEntityMultiblockMetal<TileEntityRefinery,RefineryRecipe> implements IAdvancedSelectionBounds,IAdvancedCollisionBounds, IGuiTile
{
public TileEntityRefinery()
{
super(MultiblockRefinery.instance, new int[]{3,3,5}, 16000, true);
}
public FluidTank[] tanks = new FluidTank[]{new FluidTank(24000),new FluidTank(24000),new FluidTank(24000)};
public ItemStack[] inventory = new ItemStack[6];
@Override
public void readCustomNBT(NBTTagCompound nbt, boolean descPacket)
{
super.readCustomNBT(nbt, descPacket);
tanks[0].readFromNBT(nbt.getCompoundTag("tank0"));
tanks[1].readFromNBT(nbt.getCompoundTag("tank1"));
tanks[2].readFromNBT(nbt.getCompoundTag("tank2"));
if(!descPacket)
inventory = Utils.readInventory(nbt.getTagList("inventory", 10), 6);
}
@Override
public void writeCustomNBT(NBTTagCompound nbt, boolean descPacket)
{
super.writeCustomNBT(nbt, descPacket);
nbt.setTag("tank0", tanks[0].writeToNBT(new NBTTagCompound()));
nbt.setTag("tank1", tanks[1].writeToNBT(new NBTTagCompound()));
nbt.setTag("tank2", tanks[2].writeToNBT(new NBTTagCompound()));
if(!descPacket)
nbt.setTag("inventory", Utils.writeInventory(inventory));
}
@Override
public void update()
{
super.update();
if(worldObj.isRemote || isDummy())
return;
boolean update = false;
if(energyStorage.getEnergyStored()>0 && processQueue.size()<this.getProcessQueueMaxLength())
{
if(tanks[0].getFluidAmount()>0 || tanks[1].getFluidAmount()>0)
{
RefineryRecipe recipe = RefineryRecipe.findRecipe(tanks[0].getFluid(), tanks[1].getFluid());
if(recipe!=null)
{
MultiblockProcessInMachine<RefineryRecipe> process = new MultiblockProcessInMachine(recipe).setInputTanks((tanks[0].getFluidAmount()>0&&tanks[1].getFluidAmount()>0)?new int[]{0,1}: tanks[0].getFluidAmount()>0?new int[]{0}: new int[]{1});
if(this.addProcessToQueue(process, true))
{
this.addProcessToQueue(process, false);
update = true;
}
}
}
}
if(this.tanks[2].getFluidAmount()>0)
{
ItemStack filledContainer = Utils.fillFluidContainer(tanks[2], inventory[4], inventory[5], null);
if(filledContainer!=null)
{
if(inventory[5]!=null && OreDictionary.itemMatches(inventory[5], filledContainer, true))
inventory[5].stackSize+=filledContainer.stackSize;
else if(inventory[5]==null)
inventory[5] = filledContainer.copy();
if(--inventory[4].stackSize<=0)
inventory[4]=null;
update = true;
}
if(this.tanks[2].getFluidAmount()>0)
{
FluidStack out = Utils.copyFluidStackWithAmount(this.tanks[2].getFluid(), Math.min(this.tanks[2].getFluidAmount(), 80), false);
BlockPos outputPos = this.getPos().add(0,-1,0).offset(facing.getOpposite());
IFluidHandler output = FluidUtil.getFluidHandler(worldObj, outputPos, facing);
if(output!=null)
{
int accepted = output.fill(out, false);
if(accepted>0)
{
int drained = output.fill(Utils.copyFluidStackWithAmount(out,Math.min(out.amount, accepted),false), true);
this.tanks[2].drain(drained, true);
update=true;
}
}
}
}
ItemStack emptyContainer = Utils.drainFluidContainer(tanks[0], inventory[0], inventory[1], null);
if(emptyContainer!=null && emptyContainer.stackSize>0)
{
if(inventory[1]!=null && OreDictionary.itemMatches(inventory[1], emptyContainer, true))
inventory[1].stackSize+=emptyContainer.stackSize;
else if(inventory[1]==null)
inventory[1] = emptyContainer.copy();
if(--inventory[0].stackSize<=0)
inventory[0]=null;
update = true;
}
emptyContainer = Utils.drainFluidContainer(tanks[1], inventory[2], inventory[3], null);
if(emptyContainer!=null && emptyContainer.stackSize>0)
{
if(inventory[3]!=null && OreDictionary.itemMatches(inventory[3], emptyContainer, true))
inventory[3].stackSize+=emptyContainer.stackSize;
else if(inventory[3]==null)
inventory[3] = emptyContainer.copy();
if(--inventory[2].stackSize<=0)
inventory[2]=null;
update = true;
}
if(update)
{
this.markDirty();
this.markContainingBlockForUpdate(null);
}
}
@Override
public float[] getBlockBounds()
{
if(pos==0||pos==1||pos==3)
return new float[]{0,0,0, 1,.5f,1};
if(pos==19)
return new float[]{facing==EnumFacing.WEST?.5f:0,0,facing==EnumFacing.NORTH?.5f:0, facing==EnumFacing.EAST?.5f:1,1,facing==EnumFacing.SOUTH?.5f:1};
if(pos==17)
return new float[]{.0625f,0,.0625f, .9375f,1,.9375f};
return new float[]{0,0,0, 1,1,1};
}
@Override
public List<AxisAlignedBB> getAdvancedSelectionBounds()
{
EnumFacing fl = facing;
EnumFacing fw = facing.rotateY();
if(mirrored)
fw = fw.getOpposite();
if(pos==0||pos==4||pos==10||pos==14)
{
List<AxisAlignedBB> list = Lists.newArrayList(new AxisAlignedBB(0,0,0, 1,.5f,1).offset(getPos().getX(),getPos().getY(),getPos().getZ()));
if(pos>=10)
fl = fl.getOpposite();
if(pos%10==0)
fw = fw.getOpposite();
float minX = fl==EnumFacing.WEST?0: fl==EnumFacing.EAST?.75f: fw==EnumFacing.WEST?.5f: .25f;
float maxX = fl==EnumFacing.EAST?1: fl==EnumFacing.WEST?.25f: fw==EnumFacing.EAST?.5f: .75f;
float minZ = fl==EnumFacing.NORTH?0: fl==EnumFacing.SOUTH?.75f: fw==EnumFacing.NORTH?.5f: .25f;
float maxZ = fl==EnumFacing.SOUTH?1: fl==EnumFacing.NORTH?.25f: fw==EnumFacing.SOUTH?.5f: .75f;
list.add(new AxisAlignedBB(minX,.5f,minZ, maxX,1.375f,maxZ).offset(getPos().getX(),getPos().getY(),getPos().getZ()));
if(pos==4)
{
minX = fl==EnumFacing.WEST?.625f: fl==EnumFacing.EAST?.125f: .125f;
maxX = fl==EnumFacing.EAST?.375f: fl==EnumFacing.WEST?.875f: .25f;
minZ = fl==EnumFacing.NORTH?.625f: fl==EnumFacing.SOUTH?.125f: .125f;
maxZ = fl==EnumFacing.SOUTH?.375f: fl==EnumFacing.NORTH?.875f: .25f;
list.add(new AxisAlignedBB(minX,.5f,minZ, maxX,1,maxZ).offset(getPos().getX(),getPos().getY(),getPos().getZ()));
minX = fl==EnumFacing.WEST?.625f: fl==EnumFacing.EAST?.125f: .75f;
maxX = fl==EnumFacing.EAST?.375f: fl==EnumFacing.WEST?.875f: .875f;
minZ = fl==EnumFacing.NORTH?.625f: fl==EnumFacing.SOUTH?.125f: .75f;
maxZ = fl==EnumFacing.SOUTH?.375f: fl==EnumFacing.NORTH?.875f: .875f;
list.add(new AxisAlignedBB(minX,.5f,minZ, maxX,1,maxZ).offset(getPos().getX(),getPos().getY(),getPos().getZ()));
}
return list;
}
if(pos==1||pos==3||pos==11||pos==13)
{
List<AxisAlignedBB> list = Lists.newArrayList(new AxisAlignedBB(0,0,0, 1,.0f,1).offset(getPos().getX(),getPos().getY(),getPos().getZ()));
if(pos>=10)
fl = fl.getOpposite();
if(pos%10==1)
fw = fw.getOpposite();
float minX = fl==EnumFacing.WEST?0: fl==EnumFacing.EAST?.75f: fw==EnumFacing.WEST?.75f: 0;
float maxX = fl==EnumFacing.EAST?1: fl==EnumFacing.WEST?.25f: fw==EnumFacing.EAST?.25f: 1;
float minZ = fl==EnumFacing.NORTH?0: fl==EnumFacing.SOUTH?.75f: fw==EnumFacing.NORTH?.75f: 0;
float maxZ = fl==EnumFacing.SOUTH?1: fl==EnumFacing.NORTH?.25f: fw==EnumFacing.SOUTH?.25f: 1;
list.add(new AxisAlignedBB(minX,.5f,minZ, maxX,1.375f,maxZ).offset(getPos().getX(),getPos().getY(),getPos().getZ()));
return list;
}
if((pos==20||pos==24 || pos==25||pos==29)||(pos==35||pos==39 || pos==40||pos==44))
{
List<AxisAlignedBB> list = Lists.newArrayList();
if(pos%5==4)
fw = fw.getOpposite();
float minX = fl==EnumFacing.WEST?-.25f: fl==EnumFacing.EAST?-.25f: fw==EnumFacing.WEST?-1f: .5f;
float maxX = fl==EnumFacing.EAST?1.25f: fl==EnumFacing.WEST?1.25f: fw==EnumFacing.EAST?2: .5f;
float minZ = fl==EnumFacing.NORTH?-.25f: fl==EnumFacing.SOUTH?-.25f: fw==EnumFacing.NORTH?-1f: .5f;
float maxZ = fl==EnumFacing.SOUTH?1.25f: fl==EnumFacing.NORTH?1.25f: fw==EnumFacing.SOUTH?2: .5f;
float minY = pos<35?.5f:-.5f;
float maxY = pos<35?2f:1f;
if(pos%15>=10)
{
minX += fl==EnumFacing.WEST?1: fl==EnumFacing.EAST?-1: 0;
maxX += fl==EnumFacing.WEST?1: fl==EnumFacing.EAST?-1: 0;
minZ += fl==EnumFacing.NORTH?1: fl==EnumFacing.SOUTH?-1: 0;
maxZ += fl==EnumFacing.NORTH?1: fl==EnumFacing.SOUTH?-1: 0;
}
list.add(new AxisAlignedBB(minX,minY,minZ, maxX,maxY,maxZ).offset(getPos().getX(),getPos().getY(),getPos().getZ()));
return list;
}
if((pos==21||pos==23 || pos==26||pos==28)||(pos==36||pos==38 || pos==41||pos==43))
{
List<AxisAlignedBB> list = Lists.newArrayList();
if(pos%5==3)
fw = fw.getOpposite();
float minX = fl==EnumFacing.WEST?-.25f: fl==EnumFacing.EAST?-.25f: fw==EnumFacing.WEST?0f:-.5f;
float maxX = fl==EnumFacing.EAST?1.25f: fl==EnumFacing.WEST?1.25f: fw==EnumFacing.EAST?1f: 1.5f;
float minZ = fl==EnumFacing.NORTH?-.25f: fl==EnumFacing.SOUTH?-.25f: fw==EnumFacing.NORTH?0:-.5f;
float maxZ = fl==EnumFacing.SOUTH?1.25f: fl==EnumFacing.NORTH?1.25f: fw==EnumFacing.SOUTH?1f: 1.5f;
float minY = pos<35?.5f:-.5f;
float maxY = pos<35?2f:1f;
if(pos%15>=10)
{
minX += fl==EnumFacing.WEST?1: fl==EnumFacing.EAST?-1: 0;
maxX += fl==EnumFacing.WEST?1: fl==EnumFacing.EAST?-1: 0;
minZ += fl==EnumFacing.NORTH?1: fl==EnumFacing.SOUTH?-1: 0;
maxZ += fl==EnumFacing.NORTH?1: fl==EnumFacing.SOUTH?-1: 0;
}
list.add(new AxisAlignedBB(minX,minY,minZ, maxX,maxY,maxZ).offset(getPos().getX(),getPos().getY(),getPos().getZ()));
return list;
}
return null;
}
@Override
public boolean isOverrideBox(AxisAlignedBB box, EntityPlayer player, RayTraceResult mop, ArrayList<AxisAlignedBB> list)
{
return false;
}
@Override
public List<AxisAlignedBB> getAdvancedColisionBounds()
{
return getAdvancedSelectionBounds();
}
@Override
public int[] getEnergyPos()
{
return new int[]{27};
}
@Override
public int[] getRedstonePos()
{
return new int[]{19};
}
@Override
public boolean isInWorldProcessingMachine()
{
return false;
}
@Override
public boolean additionalCanProcessCheck(MultiblockProcess<RefineryRecipe> process)
{
return true;
}
@Override
public void doProcessOutput(ItemStack output)
{
BlockPos pos = getPos().offset(facing,2);
TileEntity inventoryTile = this.worldObj.getTileEntity(pos);
if(inventoryTile!=null)
output = Utils.insertStackIntoInventory(inventoryTile, output, facing.getOpposite());
if(output!=null)
Utils.dropStackAtPos(worldObj, pos, output, facing);
}
@Override
public void doProcessFluidOutput(FluidStack output)
{
}
@Override
public void onProcessFinish(MultiblockProcess<RefineryRecipe> process)
{
}
@Override
public int getMaxProcessPerTick()
{
return 1;
}
@Override
public int getProcessQueueMaxLength()
{
return 1;
}
@Override
public float getMinProcessDistance(MultiblockProcess<RefineryRecipe> process)
{
return 0;
}
@Override
public ItemStack[] getInventory()
{
return inventory;
}
@Override
public boolean isStackValid(int slot, ItemStack stack)
{
return true;
}
@Override
public int getSlotLimit(int slot)
{
return 64;
}
@Override
public int[] getOutputSlots()
{
return new int[0];
}
@Override
public int[] getOutputTanks()
{
return new int[]{2};
}
@Override
public IFluidTank[] getInternalTanks()
{
return tanks;
}
@Override
protected IFluidTank[] getAccessibleFluidTanks(EnumFacing side)
{
TileEntityRefinery master = this.master();
if(master!=null)
{
if(pos == 2 && (side == null || side == facing.getOpposite()))
return new FluidTank[]{master.tanks[2]};
if((pos == 5 || pos == 9) && (side == null || side.getAxis() == facing.rotateYCCW().getAxis()))
return new FluidTank[]{master.tanks[0],master.tanks[1]};
}
return tanks;
}
@Override
protected boolean canFillTankFrom(int iTank, EnumFacing side, FluidStack resource)
{
if((pos == 5 || pos == 9) && (side == null || side.getAxis() == facing.rotateYCCW().getAxis()))
{
TileEntityRefinery master = this.master();
if(master==null || master.tanks[iTank].getFluidAmount()>=master.tanks[iTank].getCapacity())
return false;
if(master.tanks[0].getFluid()==null && master.tanks[1].getFluid()==null)
{
List<RefineryRecipe> incompleteRecipes = RefineryRecipe.findIncompleteRefineryRecipe(resource,null);
return incompleteRecipes!=null && !incompleteRecipes.isEmpty();
}
else
{
List<RefineryRecipe> incompleteRecipes = RefineryRecipe.findIncompleteRefineryRecipe(resource,master.tanks[iTank==0?1:0].getFluid());
return incompleteRecipes!=null && !incompleteRecipes.isEmpty();
}
}
return false;
}
@Override
protected boolean canDrainTankFrom(int iTank, EnumFacing side)
{
return pos==2 && (side==null||side==facing.getOpposite());
}
@Override
public void doGraphicalUpdates(int slot)
{
this.markDirty();
this.markContainingBlockForUpdate(null);
}
@Override
public RefineryRecipe findRecipeForInsertion(ItemStack inserting)
{
return null;
}
@Override
protected RefineryRecipe readRecipeFromNBT(NBTTagCompound tag)
{
return RefineryRecipe.loadFromNBT(tag);
}
@Override
public boolean canOpenGui()
{
return formed;
}
@Override
public int getGuiID()
{
return Lib.GUIID_Refinery;
}
@Override
public TileEntity getGuiMaster()
{
return master();
}
}