package blusunrize.immersiveengineering.common.blocks.metal;
import blusunrize.immersiveengineering.ImmersiveEngineering;
import blusunrize.immersiveengineering.api.crafting.CrusherRecipe;
import blusunrize.immersiveengineering.api.crafting.IngredientStack;
import blusunrize.immersiveengineering.common.Config.IEConfig;
import blusunrize.immersiveengineering.common.EventHandler;
import blusunrize.immersiveengineering.common.blocks.IEBlockInterfaces.IAdvancedCollisionBounds;
import blusunrize.immersiveengineering.common.blocks.IEBlockInterfaces.IAdvancedSelectionBounds;
import blusunrize.immersiveengineering.common.blocks.IEBlockInterfaces.ISoundTile;
import blusunrize.immersiveengineering.common.blocks.multiblocks.MultiblockCrusher;
import blusunrize.immersiveengineering.common.util.IEDamageSources;
import blusunrize.immersiveengineering.common.util.IESounds;
import blusunrize.immersiveengineering.common.util.Utils;
import com.google.common.collect.Lists;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumFacing.Axis;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.IFluidTank;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import java.util.ArrayList;
import java.util.List;
public class TileEntityCrusher extends TileEntityMultiblockMetal<TileEntityCrusher,CrusherRecipe> implements ISoundTile, IAdvancedSelectionBounds,IAdvancedCollisionBounds
{
public List<ItemStack> inputs = new ArrayList<>();
public int process = 0;
public float animation_barrelRotation=0;
// public boolean active = false;
// public boolean hasPower = false;
// public boolean mobGrinding = false;
// public int grindingTimer = 0;
// @SideOnly(Side.CLIENT)
// ItemStack particleStack;
public TileEntityCrusher()
{
super(MultiblockCrusher.instance, new int[]{3,3,5}, 32000, true);
}
@Override
public void readCustomNBT(NBTTagCompound nbt, boolean descPacket)
{
super.readCustomNBT(nbt, descPacket);
if(!descPacket)
{
NBTTagList invList = nbt.getTagList("inputs", 10);
inputs.clear();
for(int i=0;i<invList.tagCount();i++)
inputs.add( ItemStack.loadItemStackFromNBT(invList.getCompoundTagAt(i)));
}
}
@Override
public void writeCustomNBT(NBTTagCompound nbt, boolean descPacket)
{
super.writeCustomNBT(nbt, descPacket);
if(!descPacket)
{
NBTTagList invList = new NBTTagList();
for(ItemStack s : inputs)
invList.appendTag(s.writeToNBT(new NBTTagCompound()));
nbt.setTag("inputs", invList);
}
}
@Override
public void update()
{
super.update();
if(worldObj.isRemote && !isDummy())
{
boolean active = shouldRenderAsActive();
ImmersiveEngineering.proxy.handleTileSound(IESounds.crusher, this, active, .5f, 1);
if(active)
{
animation_barrelRotation += 18f;
animation_barrelRotation %= 360f;
}
}
}
@SideOnly(Side.CLIENT)
private AxisAlignedBB renderAABB;
@SideOnly(Side.CLIENT)
@Override
public AxisAlignedBB getRenderBoundingBox()
{
// if(renderAABB==null)
// if(pos==17)
// renderAABB = AxisAlignedBB.getBoundingBox(xCoord-(facing==2||facing==3?2:1),yCoord,zCoord-(facing==4||facing==5?2:1), xCoord+(facing==2||facing==3?3:2),yCoord+3,zCoord+(facing==4||facing==5?3:2));
// else
// renderAABB = AxisAlignedBB.getBoundingBox(xCoord,yCoord,zCoord, xCoord,yCoord,zCoord);
// return renderAABB;
return new AxisAlignedBB(getPos().getX()-(facing.getAxis()==Axis.Z?2:1),getPos().getY(),getPos().getZ()-(facing.getAxis()==Axis.X?2:1), getPos().getX()+(facing.getAxis()==Axis.Z?3:2),getPos().getY()+3,getPos().getZ()+(facing.getAxis()==Axis.X?3:2));
}
@Override
@SideOnly(Side.CLIENT)
public double getMaxRenderDistanceSquared()
{
return super.getMaxRenderDistanceSquared()* IEConfig.increasedTileRenderdistance;
}
@Override
public float[] getBlockBounds()
{
if(pos==1||pos==3||pos==4||pos==6||pos==8||pos==11||pos==12||pos==13||pos==14||pos==24)
return new float[]{0,0,0,1,.5f,1};
if(pos==22)
return new float[]{0,0,0, 1,.75f,1};
if(pos==37)
return new float[]{0,0,0, 0,0,0};
EnumFacing fl = facing;
EnumFacing fw = facing.rotateY();
if(mirrored)
fw = fw.getOpposite();
if(pos>15 && pos%5>0&&pos%5<4)
{
float minX = 0;
float maxX = 1;
float minZ = 0;
float maxZ = 1;
if(pos%5==1)
{
minX = fw==EnumFacing.EAST?.1875f: 0;
maxX = fw==EnumFacing.WEST?.8125f: 1;
minZ = fw==EnumFacing.SOUTH?.1875f: 0;
maxZ = fw==EnumFacing.NORTH?.8125f: 1;
}
else if(pos%5==3)
{
minX = fw==EnumFacing.WEST?.1875f: 0;
maxX = fw==EnumFacing.EAST?.8125f: 1;
minZ = fw==EnumFacing.NORTH?.1875f: 0;
maxZ = fw==EnumFacing.SOUTH?.8125f: 1;
}
if((pos%15)/5==0)
{
if(fl==EnumFacing.EAST)
minX = .1875f;
if(fl==EnumFacing.WEST)
maxX = .8125f;
if(fl==EnumFacing.SOUTH)
minZ = .1875f;
if(fl==EnumFacing.NORTH)
maxZ = .8125f;
}
return new float[]{minX,0,minZ, maxX,1,maxZ};
}
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};
return new float[]{0,0,0,1,1,1};
}
@Override
public List<AxisAlignedBB> getAdvancedSelectionBounds()
{
if(pos%15==7)
return null;
EnumFacing fl = facing;
EnumFacing fw = facing.rotateY();
if(mirrored)
fw = fw.getOpposite();
if(pos==4)
{
List<AxisAlignedBB> list = Lists.newArrayList(new AxisAlignedBB(0,0,0, 1,.5f,1).offset(getPos().getX(),getPos().getY(),getPos().getZ()));
float minX = fl==EnumFacing.WEST?.625f: fl==EnumFacing.EAST?.125f: .125f;
float maxX = fl==EnumFacing.EAST?.375f: fl==EnumFacing.WEST?.875f: .25f;
float minZ = fl==EnumFacing.NORTH?.625f: fl==EnumFacing.SOUTH?.125f: .125f;
float 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>20 && pos<24)||(pos>35 && pos<39))
{
List<AxisAlignedBB> list = new ArrayList<AxisAlignedBB>(3);
float minY = .5f;
float minX = (pos%5==1&&fw==EnumFacing.EAST)||(pos%5==3&&fw==EnumFacing.WEST)?.4375f: 0;
float maxX = (pos%5==1&&fw==EnumFacing.WEST)||(pos%5==3&&fw==EnumFacing.EAST)?.5625f: 1;
float minZ = (pos%5==1&&fw==EnumFacing.SOUTH)||(pos%5==3&&fw==EnumFacing.NORTH)?.4375f: 0;
float maxZ = (pos%5==1&&fw==EnumFacing.NORTH)||(pos%5==3&&fw==EnumFacing.SOUTH)?.5625f: 1;
if(pos>20 && pos<24)
list.add(new AxisAlignedBB(minX,.5f,minZ, maxX,.75f,maxZ).offset(getPos().getX(),getPos().getY(),getPos().getZ()));
else
minY = 0;
minX = (pos%5==1&&fw==EnumFacing.EAST)||(pos%5==3&&fw==EnumFacing.WEST)?.1875f: (pos%5==1&&fw==EnumFacing.WEST)||(pos%5==3&&fw==EnumFacing.EAST)?.5625f: 0;
maxX = (pos%5==1&&fw==EnumFacing.WEST)||(pos%5==3&&fw==EnumFacing.EAST)?.8125f: (pos%5==1&&fw==EnumFacing.EAST)||(pos%5==3&&fw==EnumFacing.WEST)?.4375f: 1;
minZ = (pos%5==1&&fw==EnumFacing.SOUTH)||(pos%5==3&&fw==EnumFacing.NORTH)?.1875f: (pos%5==1&&fw==EnumFacing.NORTH)||(pos%5==3&&fw==EnumFacing.SOUTH)?.5625f: 0;
maxZ = (pos%5==1&&fw==EnumFacing.NORTH)||(pos%5==3&&fw==EnumFacing.SOUTH)?.8125f: (pos%5==1&&fw==EnumFacing.SOUTH)||(pos%5==3&&fw==EnumFacing.NORTH)?.4375f :1;
list.add(new AxisAlignedBB(minX,minY,minZ, maxX,1,maxZ).offset(getPos().getX(),getPos().getY(),getPos().getZ()));
return list;
}
if((pos>15 && pos<19)||(pos>30 && pos<34)||(pos>25 && pos<29)||(pos>40 && pos<44))
{
if(pos%15>9)
fl = fl.getOpposite();
List<AxisAlignedBB> list = new ArrayList<AxisAlignedBB>(3);
float minY = .5f;
float minX = (pos%5==1&&fw==EnumFacing.EAST)||(pos%5==3&&fw==EnumFacing.WEST)?.4375f: fl==EnumFacing.EAST?.4375f: 0;
float maxX = (pos%5==1&&fw==EnumFacing.WEST)||(pos%5==3&&fw==EnumFacing.EAST)?.5625f: fl==EnumFacing.WEST?.5625f: 1;
float minZ = (pos%5==1&&fw==EnumFacing.SOUTH)||(pos%5==3&&fw==EnumFacing.NORTH)?.4375f: fl==EnumFacing.SOUTH?.4375f: 0;
float maxZ = (pos%5==1&&fw==EnumFacing.NORTH)||(pos%5==3&&fw==EnumFacing.SOUTH)?.5625f: fl==EnumFacing.NORTH?.5625f: 1;
if((pos>15 && pos<19) || (pos>25 && pos<29))
list.add(new AxisAlignedBB(minX,.5f,minZ, maxX,.75f,maxZ).offset(getPos().getX(),getPos().getY(),getPos().getZ()));
else
minY = 0;
if(pos/15>9)
fl = fl.getOpposite();
minX = (pos%5==1&&fw==EnumFacing.EAST)||(pos%5==3&&fw==EnumFacing.WEST)?.1875f: fl==EnumFacing.EAST?.1875f: fl==EnumFacing.WEST?.5625f: 0;
maxX = (pos%5==1&&fw==EnumFacing.WEST)||(pos%5==3&&fw==EnumFacing.EAST)?.8125f: fl==EnumFacing.WEST?.8125f: fl==EnumFacing.EAST?.4375f: 1;
minZ = (pos%5==1&&fw==EnumFacing.SOUTH)||(pos%5==3&&fw==EnumFacing.NORTH)?.1875f: fl==EnumFacing.SOUTH?.1875f: fl==EnumFacing.NORTH?.5625f: 0;
maxZ = (pos%5==1&&fw==EnumFacing.NORTH)||(pos%5==3&&fw==EnumFacing.SOUTH)?.8125f: fl==EnumFacing.NORTH?.8125f: fl==EnumFacing.SOUTH?.4375f: 1;
list.add(new AxisAlignedBB(minX,minY,minZ, maxX,1,maxZ).offset(getPos().getX(),getPos().getY(),getPos().getZ()));
if(pos!=17&&pos!=32 && pos!=27&&pos!=42)
{
minX = (pos%5==1&&fw==EnumFacing.EAST)||(pos%5==3&&fw==EnumFacing.WEST)?.1875f: fl==EnumFacing.EAST?.4375f: fl==EnumFacing.WEST?0: .5625f;
maxX = (pos%5==1&&fw==EnumFacing.WEST)||(pos%5==3&&fw==EnumFacing.EAST)?.8125f: fl==EnumFacing.WEST?.5625f: fl==EnumFacing.EAST?1: .4375f;
minZ = (pos%5==1&&fw==EnumFacing.SOUTH)||(pos%5==3&&fw==EnumFacing.NORTH)?.1875f: fl==EnumFacing.SOUTH?.4375f: fl==EnumFacing.NORTH?0: .5625f;
maxZ = (pos%5==1&&fw==EnumFacing.NORTH)||(pos%5==3&&fw==EnumFacing.SOUTH)?.8125f: fl==EnumFacing.NORTH?.5625f: fl==EnumFacing.SOUTH?1: .4375f;
list.add(new AxisAlignedBB(minX,minY,minZ, maxX,1,maxZ).offset(getPos().getX(),getPos().getY(),getPos().getZ()));
if(pos%15%10==1)
fw = fw.getOpposite();
if((pos>15 && pos<19) || (pos>25 && pos<29))
{
minX = fl==EnumFacing.WEST?.5f: fl==EnumFacing.EAST?.25f: fw==EnumFacing.EAST?.5f: .25f;
maxX = fl==EnumFacing.EAST?.5f: fl==EnumFacing.WEST?.75f: fw==EnumFacing.EAST?.75f: .5f;
minZ = fl==EnumFacing.NORTH?.5f: fl==EnumFacing.SOUTH?.25f: fw==EnumFacing.SOUTH?.5f: .25f;
maxZ = fl==EnumFacing.SOUTH?.5f: fl==EnumFacing.NORTH?.75f: fw==EnumFacing.SOUTH?.75f: .5f;
list.add(new AxisAlignedBB(minX,0,minZ, maxX,.5f,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,.5f,1).offset(getPos().getX(),getPos().getY(),getPos().getZ()));
if(pos%15>9)
fl = fl.getOpposite();
if(pos%15%10==1)
fw = fw.getOpposite();
float minX = fl==EnumFacing.WEST?.5f: fl==EnumFacing.EAST?.25f: fw==EnumFacing.EAST?.5f: .25f;
float maxX = fl==EnumFacing.EAST?.5f: fl==EnumFacing.WEST?.75f: fw==EnumFacing.EAST?.75f: .5f;
float minZ = fl==EnumFacing.NORTH?.5f: fl==EnumFacing.SOUTH?.25f: fw==EnumFacing.SOUTH?.5f: .25f;
float maxZ = fl==EnumFacing.SOUTH?.5f: fl==EnumFacing.NORTH?.75f: fw==EnumFacing.SOUTH?.75f: .5f;
list.add(new AxisAlignedBB(minX,.5f,minZ, maxX,1,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 void onEntityCollision(World world, Entity entity)
{
boolean bpos = pos==16||pos==17||pos==18||pos==21||pos==22||pos==23||pos==26||pos==27||pos==28;
if(bpos && !world.isRemote && entity!=null && !entity.isDead&&!isRSDisabled())
{
TileEntityCrusher master = master();
if(master==null)
return;
Vec3d center = new Vec3d(master.getPos()).addVector(.5,.75,.5);
AxisAlignedBB crusherInternal = new AxisAlignedBB(center.xCoord-1.0625,center.yCoord,center.zCoord-1.0625, center.xCoord+1.0625,center.yCoord+1.25,center.zCoord+1.0625);
if(!entity.getEntityBoundingBox().intersectsWith(crusherInternal))
return;
if(entity instanceof EntityItem && ((EntityItem)entity).getEntityItem()!=null)
{
ItemStack stack = ((EntityItem)entity).getEntityItem();
if(stack==null)
return;
CrusherRecipe recipe = master.findRecipeForInsertion(stack);
if(recipe==null)
return;
ItemStack displayStack = null;
for(IngredientStack ingr : recipe.getItemInputs())
if(ingr.matchesItemStack(stack))
{
displayStack = Utils.copyStackWithAmount(stack, ingr.inputSize);
break;
}
MultiblockProcess<CrusherRecipe> process = new MultiblockProcessInWorld<CrusherRecipe>(recipe, .5f, displayStack);
if(master.addProcessToQueue(process, true, true))
{
master.addProcessToQueue(process, false, true);
stack.stackSize -= displayStack.stackSize;
if(stack.stackSize<=0)
entity.setDead();
}
}
else if(entity instanceof EntityLivingBase && ( !(entity instanceof EntityPlayer) || !((EntityPlayer)entity).capabilities.disableDamage) )
{
int consumed = master.energyStorage.extractEnergy(80, true);
if(consumed>0)
{
master.energyStorage.extractEnergy(consumed, false);
EventHandler.crusherMap.put(entity.getUniqueID(), master);
entity.attackEntityFrom(IEDamageSources.crusher, consumed/20f);
}
}
}
}
@Override
public int[] getEnergyPos()
{
return new int[]{20};
}
@Override
public int[] getRedstonePos()
{
return new int[]{19};
}
@Override
public boolean isInWorldProcessingMachine()
{
return true;
}
@Override
public boolean additionalCanProcessCheck(MultiblockProcess<CrusherRecipe> process)
{
return true;
}
@Override
public void doProcessOutput(ItemStack output)
{
BlockPos pos = getPos().add(0,-1,0).offset(facing,-2);
TileEntity inventoryTile = this.worldObj.getTileEntity(pos);
if(inventoryTile!=null)
output = Utils.insertStackIntoInventory(inventoryTile, output, facing);
if(output!=null)
Utils.dropStackAtPos(worldObj, pos, output, facing.getOpposite());
}
@Override
public void doProcessFluidOutput(FluidStack output)
{
}
@Override
public void onProcessFinish(MultiblockProcess<CrusherRecipe> process)
{
}
@Override
public int getMaxProcessPerTick()
{
return 1;
}
@Override
public int getProcessQueueMaxLength()
{
return -1;
}
@Override
public float getMinProcessDistance(MultiblockProcess<CrusherRecipe> process)
{
return 0;
}
@Override
public ItemStack[] getInventory()
{
return null;
}
@Override
public boolean isStackValid(int slot, ItemStack stack)
{
return false;
}
@Override
public int getSlotLimit(int slot)
{
return 0;
}
@Override
public int[] getOutputSlots()
{
return null;
}
@Override
public int[] getOutputTanks()
{
return null;
}
@Override
public IFluidTank[] getInternalTanks()
{
return null;
}
@Override
protected IFluidTank[] getAccessibleFluidTanks(EnumFacing side)
{
return new IFluidTank[0];
}
@Override
protected boolean canFillTankFrom(int iTank, EnumFacing side, FluidStack resources)
{
return false;
}
@Override
protected boolean canDrainTankFrom(int iTank, EnumFacing side)
{
return false;
}
@Override
public void doGraphicalUpdates(int slot)
{
}
@Override
public boolean hasCapability(Capability<?> capability, EnumFacing facing)
{
if(pos>30&&pos<44 && pos%5>0&&pos%5<4 && capability==CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
return true;
return super.hasCapability(capability, facing);
}
IItemHandler insertionHandler = new MultiblockInventoryHandler_DirectProcessing(this).setProcessStacking(true);
@Override
public <T> T getCapability(Capability<T> capability, EnumFacing facing)
{
if(pos>30&&pos<44 && pos%5>0&&pos%5<4 && capability==CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
{
TileEntityCrusher master = master();
if(master!=null)
return (T)master.insertionHandler;
return null;
}
return super.getCapability(capability, facing);
}
@Override
public CrusherRecipe findRecipeForInsertion(ItemStack inserting)
{
return CrusherRecipe.findRecipe(inserting);
}
@Override
protected CrusherRecipe readRecipeFromNBT(NBTTagCompound tag)
{
return CrusherRecipe.loadFromNBT(tag);
}
@Override
public boolean shoudlPlaySound(String sound)
{
return shouldRenderAsActive();
}
}