package blusunrize.immersiveengineering.common.blocks.metal;
import blusunrize.immersiveengineering.ImmersiveEngineering;
import blusunrize.immersiveengineering.api.crafting.IMultiblockRecipe;
import blusunrize.immersiveengineering.api.tool.ExcavatorHandler;
import blusunrize.immersiveengineering.common.Config.IEConfig;
import blusunrize.immersiveengineering.common.blocks.IEBlockInterfaces.IAdvancedCollisionBounds;
import blusunrize.immersiveengineering.common.blocks.IEBlockInterfaces.IAdvancedSelectionBounds;
import blusunrize.immersiveengineering.common.blocks.multiblocks.MultiblockExcavator;
import blusunrize.immersiveengineering.common.util.FakePlayerUtil;
import blusunrize.immersiveengineering.common.util.Utils;
import blusunrize.immersiveengineering.common.util.network.MessageTileSync;
import com.google.common.collect.Lists;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.item.Item;
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.minecraft.world.WorldServer;
import net.minecraftforge.common.util.FakePlayer;
import net.minecraftforge.event.ForgeEventFactory;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.IFluidTank;
import java.util.ArrayList;
import java.util.List;
public class TileEntityExcavator extends TileEntityMultiblockMetal<TileEntityExcavator,IMultiblockRecipe> implements IAdvancedSelectionBounds,IAdvancedCollisionBounds
{
public TileEntityExcavator()
{
super(MultiblockExcavator.instance, new int[]{3,6,3}, 64000, true);
}
public boolean active = false;
@Override
public void readCustomNBT(NBTTagCompound nbt, boolean descPacket)
{
super.readCustomNBT(nbt, descPacket);
}
@Override
public void writeCustomNBT(NBTTagCompound nbt, boolean descPacket)
{
super.writeCustomNBT(nbt, descPacket);
}
@Override
public void update()
{
super.update();
if(isDummy())
return;
if(!worldObj.isRemote)
{
BlockPos wheelPos = this.getBlockPosForPos(31);
TileEntity center = worldObj.getTileEntity(wheelPos);
if(center instanceof TileEntityBucketWheel)
{
float rot = 0;
int target = -1;
TileEntityBucketWheel wheel = ((TileEntityBucketWheel) center);
EnumFacing fRot = this.facing.rotateYCCW();
if(wheel.facing==fRot)
{
if(active!=wheel.active)
worldObj.addBlockEvent(wheel.getPos(), wheel.getBlockType(), 0, active? 1: 0);
rot = wheel.rotation;
if(rot%45>40)
target = Math.round(rot/360f*8)%8;
}
if(wheel.facing!=fRot || wheel.mirrored!=this.mirrored)
{
for(int h = -3; h <= 3; h++)
for(int w = -3; w <= 3; w++)
{
TileEntity te = worldObj.getTileEntity(wheelPos.add(0, h, 0).offset(facing, w));
if(te instanceof TileEntityBucketWheel)
{
((TileEntityBucketWheel)te).facing = fRot;
((TileEntityBucketWheel)te).mirrored = this.mirrored;
te.markDirty();
((TileEntityBucketWheel)te).markContainingBlockForUpdate(null);
worldObj.addBlockEvent(te.getPos(), te.getBlockType(), 255, 0);
}
}
}
if(!isRSDisabled())
{
ExcavatorHandler.MineralMix mineral = ExcavatorHandler.getRandomMineral(worldObj, wheelPos.getX()>>4, wheelPos.getZ()>>4);
int consumed = IEConfig.Machines.excavator_consumption;
int extracted = energyStorage.extractEnergy(consumed, true);
if(extracted>=consumed)
{
energyStorage.extractEnergy(consumed, false);
active = true;
if(target>=0 && target<8)
{
int targetDown = (target + 4) % 8;
NBTTagCompound packet = new NBTTagCompound();
if(wheel.digStacks[targetDown] == null)
{
ItemStack blocking = this.digBlocksInTheWay(wheel);
BlockPos lowGroundPos = wheelPos.add(0,-5,0);
if(blocking!=null)
{
wheel.digStacks[targetDown] = blocking;
wheel.markDirty();
this.markContainingBlockForUpdate(null);
} else if(mineral != null
&& !worldObj.isAirBlock(lowGroundPos.offset(facing, -2))
&& !worldObj.isAirBlock(lowGroundPos.offset(facing, 2))
&& !worldObj.isAirBlock(lowGroundPos.offset(facing, -1))
&& !worldObj.isAirBlock(lowGroundPos.offset(facing, 1))
&& !worldObj.isAirBlock(lowGroundPos))
{
ItemStack ore = mineral.getRandomOre(worldObj.rand);
float configChance = worldObj.rand.nextFloat();
float failChance = worldObj.rand.nextFloat();
if(ore!=null && configChance> IEConfig.Machines.excavator_fail_chance && failChance>mineral.failChance)
{
wheel.digStacks[targetDown] = ore;
wheel.markDirty();
this.markContainingBlockForUpdate(null);
}
ExcavatorHandler.depleteMinerals(worldObj, wheelPos.getX()>>4, wheelPos.getZ()>>4);
}
if(wheel.digStacks[targetDown] != null)
{
packet.setInteger("fill", targetDown);
packet.setTag("fillStack", wheel.digStacks[targetDown].writeToNBT(new NBTTagCompound()));
}
}
if(wheel.digStacks[target]!=null)
{
this.doProcessOutput(wheel.digStacks[target].copy());
Block b = Block.getBlockFromItem(wheel.digStacks[target].getItem());
if(b!=null&&b!=Blocks.AIR)
wheel.particleStack = wheel.digStacks[target].copy();
wheel.digStacks[target] = null;
wheel.markDirty();
this.markContainingBlockForUpdate(null);
packet.setInteger("empty", target);
}
if(!packet.hasNoTags())
ImmersiveEngineering.packetHandler.sendToAll(new MessageTileSync(wheel, packet));
}
}
else if(active)
active=false;
}
else if(active)
{
active=false;
// update = true;
}
// if(update)
// {
// this.markDirty();
// worldObj.markBlockForUpdate(xCoord, yCoord, zCoord);
// }
}
}
}
ItemStack digBlocksInTheWay(TileEntityBucketWheel wheel)
{
BlockPos pos = wheel.getPos().add(0,-4,0);
ItemStack s = digBlock(pos);
if(s!=null)
return s;
//Backward 1
s = digBlock(pos.offset(facing,-1));
if(s!=null)
return s;
//Backward 2
s = digBlock(pos.offset(facing,-2));
if(s!=null)
return s;
//Forward 1
s = digBlock(pos.offset(facing,1));
if(s!=null)
return s;
//Forward 2
s = digBlock(pos.offset(facing,2));
if(s!=null)
return s;
//Backward+Sides
s = digBlock(pos.offset(facing,-1).offset(facing.rotateY()));
if(s!=null)
return s;
s = digBlock(pos.offset(facing,-1).offset(facing.rotateYCCW()));
if(s!=null)
return s;
//Center Sides
s = digBlock(pos.offset(facing.rotateY()));
if(s!=null)
return s;
s = digBlock(pos.offset(facing.rotateYCCW()));
if(s!=null)
return s;
//Forward+Sides
s = digBlock(pos.offset(facing,1).offset(facing.rotateY()));
if(s!=null)
return s;
s = digBlock(pos.offset(facing,1).offset(facing.rotateYCCW()));
if(s!=null)
return s;
return null;
}
ItemStack digBlock(BlockPos pos)
{
if(!(worldObj instanceof WorldServer))
return null;
FakePlayer fakePlayer = FakePlayerUtil.getFakePlayer((WorldServer) worldObj);
IBlockState blockstate = worldObj.getBlockState(pos);
Block block = blockstate.getBlock();
if(block!=null && !worldObj.isAirBlock(pos) && blockstate.getPlayerRelativeBlockHardness(fakePlayer, worldObj, pos)!=0)
{
if(!block.canHarvestBlock(worldObj, pos, fakePlayer))
return null;
block.onBlockHarvested(worldObj, pos, blockstate, fakePlayer);
if(block.removedByPlayer(blockstate, worldObj, pos, fakePlayer, true))
{
block.onBlockDestroyedByPlayer( worldObj, pos, blockstate);
if(block.canSilkHarvest(worldObj, pos, blockstate, fakePlayer))
{
ArrayList<ItemStack> items = new ArrayList<ItemStack>();
Item bitem = Item.getItemFromBlock(block);
if(bitem==null)
return null;
ItemStack itemstack = new ItemStack(bitem, 1, block.getMetaFromState(blockstate));
if (itemstack != null)
items.add(itemstack);
ForgeEventFactory.fireBlockHarvesting(items, worldObj, pos, blockstate, 0, 1.0f, true, fakePlayer);
for(int i=0; i<items.size(); i++)
if(i!=0)
{
EntityItem ei = new EntityItem(worldObj, pos.getX()+.5,pos.getY()+.5,pos.getZ()+.5, items.get(i).copy());
this.worldObj.spawnEntityInWorld(ei);
}
worldObj.playEvent(2001, pos, Block.getStateId(blockstate));
if(items.size()>0)
return items.get(0);
}
else
{
block.harvestBlock(worldObj, fakePlayer, pos, blockstate, worldObj.getTileEntity(pos), null);
worldObj.playEvent(2001, pos, Block.getStateId(blockstate));
}
}
}
return null;
}
@Override
public float[] getBlockBounds()
{
EnumFacing fl = facing;
EnumFacing fw = facing.rotateY();
if(mirrored)
fw = fw.getOpposite();
if(pos==45)
return new float[]{fl==EnumFacing.EAST?.5f:0,0,fl==EnumFacing.SOUTH?.5f:0, fl==EnumFacing.WEST?.5f:1,.5f,fl==EnumFacing.NORTH?.5f:1};
if(pos==48)
return new float[]{0,0,0, 1,.5f,1};
if(pos==51)
return new float[]{fl==EnumFacing.WEST?.5f:0,0,fl==EnumFacing.NORTH?.5f:0, fl==EnumFacing.EAST?.5f:1,.5f,fl==EnumFacing.SOUTH?.5f:1};
if(pos==47)
return new float[]{fl==EnumFacing.EAST?.5f:fl==EnumFacing.WEST?.375f:0,0,fl==EnumFacing.SOUTH?.5f:fl==EnumFacing.NORTH?.375f:0, fl==EnumFacing.WEST?.5f:fl==EnumFacing.EAST?.625f:1,1,fl==EnumFacing.NORTH?.5f:fl==EnumFacing.SOUTH?.625f:1};
if(pos==50)
return new float[]{fw==EnumFacing.EAST?.875f:0,0,fw==EnumFacing.SOUTH?.875f:0, fw==EnumFacing.WEST?.125f:1,1,fw==EnumFacing.NORTH?.125f:1};
if(pos==53)
return new float[]{fl==EnumFacing.WEST?.5f:fl==EnumFacing.EAST?.375f:0,0,fl==EnumFacing.NORTH?.5f:fl==EnumFacing.SOUTH?.375f:0, fl==EnumFacing.EAST?.5f:fl==EnumFacing.WEST?.625f:1,1,fl==EnumFacing.SOUTH?.5f:fl==EnumFacing.NORTH?.625f:1};
if(pos==5||pos==23||pos==41)
return new float[]{fw==EnumFacing.WEST?.5f:0,0,fw==EnumFacing.NORTH?.5f:0, fw==EnumFacing.EAST?.5f:1,1,fw==EnumFacing.SOUTH?.5f:1};
if(pos==9||pos==12||pos==15)
return new float[]{fw==EnumFacing.EAST?.5f:0,0,fw==EnumFacing.SOUTH?.5f:0, fw==EnumFacing.WEST?.5f:1,1,fw==EnumFacing.NORTH?.5f:1};
if(pos==11||pos==14||pos==17)
return new float[]{fw==EnumFacing.WEST?.5f:0,0,fw==EnumFacing.NORTH?.5f:0, fw==EnumFacing.EAST?.5f:1,1,fw==EnumFacing.SOUTH?.5f:1};
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==5||pos==23||pos==41)
{
List list = Lists.newArrayList(new AxisAlignedBB(fw==EnumFacing.WEST?.5f:0,0,fw==EnumFacing.NORTH?.5f:0, fw==EnumFacing.EAST?.5f:1,1,fw==EnumFacing.SOUTH?.5f:1).offset(getPos().getX(),getPos().getY(),getPos().getZ()));
list.add(new AxisAlignedBB(fw==EnumFacing.EAST?.5f:fw==EnumFacing.WEST?0:.25f,.25f,fw==EnumFacing.SOUTH?.5f:fw==EnumFacing.NORTH?0:.25f, fw==EnumFacing.WEST?.5f:fw==EnumFacing.EAST?1:.75f,.75f,fw==EnumFacing.NORTH?.5f:fw==EnumFacing.SOUTH?1:.75f).offset(getPos().getX(),getPos().getY(),getPos().getZ()));
return list;
}
else if(pos==9||pos==12||pos==15)
{
List list = Lists.newArrayList(new AxisAlignedBB(fw==EnumFacing.EAST?.5f:0,0,fw==EnumFacing.SOUTH?.5f:0, fw==EnumFacing.WEST?.5f:1,1,fw==EnumFacing.NORTH?.5f:1).offset(getPos().getX(),getPos().getY(),getPos().getZ()));
if(pos==9)
list.add(new AxisAlignedBB(fw==EnumFacing.WEST||fl==EnumFacing.EAST?.5f:0,.5f,fw==EnumFacing.NORTH||fl==EnumFacing.SOUTH?.5f:0, fw==EnumFacing.EAST||fl==EnumFacing.WEST?.5f:1,1,fw==EnumFacing.SOUTH||fl==EnumFacing.NORTH?.5f:1).offset(getPos().getX(),getPos().getY(),getPos().getZ()));
else if(pos==12)
list.add(new AxisAlignedBB(fw==EnumFacing.WEST?.5f:0,.5f,fw==EnumFacing.NORTH?.5f:0, fw==EnumFacing.EAST?.5f:1,1,fw==EnumFacing.SOUTH?.5f:1).offset(getPos().getX(),getPos().getY(),getPos().getZ()));
else
list.add(new AxisAlignedBB(fw==EnumFacing.WEST||fl==EnumFacing.WEST?.5f:0,.5f,fw==EnumFacing.NORTH||fl==EnumFacing.NORTH?.5f:0, fw==EnumFacing.EAST||fl==EnumFacing.EAST?.5f:1,1,fw==EnumFacing.SOUTH||fl==EnumFacing.SOUTH?.5f:1).offset(getPos().getX(),getPos().getY(),getPos().getZ()));
return list;
}
else if(pos==47)
{
List list = Lists.newArrayList(new AxisAlignedBB(fl==EnumFacing.EAST?.5f:fl==EnumFacing.WEST?.375f:0,0,fl==EnumFacing.SOUTH?.5f:fl==EnumFacing.NORTH?.375f:0, fl==EnumFacing.WEST?.5f:fl==EnumFacing.EAST?.625f:1,1,fl==EnumFacing.NORTH?.5f:fl==EnumFacing.SOUTH?.625f:1).offset(getPos().getX(),getPos().getY(),getPos().getZ()));
list.add(new AxisAlignedBB(fl==EnumFacing.EAST?.625f:fw==EnumFacing.EAST?.875f:0,0,fl==EnumFacing.SOUTH?.625f:fw==EnumFacing.SOUTH?.875f:0, fl==EnumFacing.WEST?.375f:fw==EnumFacing.WEST?.125f:1,1,fl==EnumFacing.NORTH?.375f:fw==EnumFacing.NORTH?.125f:1).offset(getPos().getX(),getPos().getY(),getPos().getZ()));
return list;
}
else if(pos==53)
{
List list = Lists.newArrayList(new AxisAlignedBB(fl==EnumFacing.WEST?.5f:fl==EnumFacing.EAST?.375f:0,0,fl==EnumFacing.NORTH?.5f:fl==EnumFacing.SOUTH?.375f:0, fl==EnumFacing.EAST?.5f:fl==EnumFacing.WEST?.625f:1,1,fl==EnumFacing.SOUTH?.5f:fl==EnumFacing.NORTH?.625f:1).offset(getPos().getX(),getPos().getY(),getPos().getZ()));
list.add(new AxisAlignedBB(fl==EnumFacing.WEST?.625f:fw==EnumFacing.EAST?.875f:0,0,fl==EnumFacing.NORTH?.625f:fw==EnumFacing.SOUTH?.875f:0, fl==EnumFacing.EAST?.375f:fw==EnumFacing.WEST?.125f:1,1,fl==EnumFacing.SOUTH?.375f:fw==EnumFacing.NORTH?.125f:1).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[]{5,23,41};
}
@Override
public int[] getRedstonePos()
{
return new int[]{18};
}
@Override
public boolean isInWorldProcessingMachine()
{
return false;
}
@Override
public boolean additionalCanProcessCheck(MultiblockProcess<IMultiblockRecipe> process)
{
return false;
}
@Override
public void doProcessOutput(ItemStack output)
{
BlockPos pos = getPos().offset(facing,-1);
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<IMultiblockRecipe> process)
{
}
@Override
public int getMaxProcessPerTick()
{
return 0;
}
@Override
public int getProcessQueueMaxLength()
{
return 0;
}
@Override
public float getMinProcessDistance(MultiblockProcess<IMultiblockRecipe> 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 new int[0];
}
@Override
public int[] getOutputTanks()
{
return new int[0];
}
@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)
{
this.markDirty();
this.markContainingBlockForUpdate(null);
}
@Override
public IMultiblockRecipe findRecipeForInsertion(ItemStack inserting)
{
return null;
}
@Override
protected IMultiblockRecipe readRecipeFromNBT(NBTTagCompound tag)
{
return null;
}
@Override
public void disassemble() {
super.disassemble();
BlockPos wheelPos = this.getBlockPosForPos(31);
TileEntity center = worldObj.getTileEntity(wheelPos);
if (center instanceof TileEntityBucketWheel)
worldObj.addBlockEvent(center.getPos(), center.getBlockType(), 0, 0);
}
}