package blusunrize.immersiveengineering.common.blocks.metal;
import blusunrize.immersiveengineering.api.energy.immersiveflux.FluxStorage;
import blusunrize.immersiveengineering.api.energy.immersiveflux.IFluxProvider;
import blusunrize.immersiveengineering.api.energy.immersiveflux.IFluxReceiver;
import blusunrize.immersiveengineering.common.Config.IEConfig;
import blusunrize.immersiveengineering.common.IEContent;
import blusunrize.immersiveengineering.common.blocks.TileEntityMultiblockPart;
import blusunrize.immersiveengineering.common.blocks.multiblocks.MultiblockLightningrod;
import blusunrize.immersiveengineering.common.util.Utils;
import cofh.api.energy.IEnergyProvider;
import net.minecraft.block.Block;
import net.minecraft.entity.effect.EntityLightningBolt;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
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.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.IFluidTank;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import javax.annotation.Nullable;
import java.util.ArrayList;
public class TileEntityLightningrod extends TileEntityMultiblockPart<TileEntityLightningrod> implements IFluxProvider,IEnergyProvider
{
FluxStorage energyStorage = new FluxStorage(IEConfig.Machines.lightning_output);
ArrayList<BlockPos> fenceNet = null;
int height;
@Override
public void update()
{
if(!worldObj.isRemote && formed && pos==13)
{
if(energyStorage.getEnergyStored()>0)
{
TileEntity tileEntity;
for(EnumFacing f : EnumFacing.HORIZONTALS)
{
tileEntity = worldObj.getTileEntity(getPos().offset(f,2));
if(tileEntity instanceof IFluxReceiver)
{
IFluxReceiver ifr = (IFluxReceiver) tileEntity;
int accepted = ifr.receiveEnergy(f.getOpposite(), energyStorage.getEnergyStored(), true);
int extracted = energyStorage.extractEnergy(accepted, false);
ifr.receiveEnergy(f.getOpposite(), extracted, false);
}
}
}
if(worldObj.getTotalWorldTime()%256==((getPos().getX()^getPos().getZ())&255))
fenceNet = null;
if(fenceNet==null)
fenceNet = this.getFenceNet();
if(fenceNet!=null && worldObj.getTotalWorldTime()%128==((getPos().getX()^getPos().getZ())&127) && ( worldObj.isThundering() || (worldObj.isRaining()&&worldObj.rand.nextInt(10)==0) ))
{
int i = this.height + this.fenceNet.size();
if(worldObj.rand.nextInt(4096*worldObj.getHeight())<i*(getPos().getY()+i))
{
this.energyStorage.setEnergy(IEConfig.Machines.lightning_output);
BlockPos pos = fenceNet.get(worldObj.rand.nextInt(fenceNet.size()));
EntityLightningBolt entityLightningBolt = new EntityLightningBolt(worldObj, pos.getX(),pos.getY(),pos.getZ(), true);
worldObj.addWeatherEffect(entityLightningBolt);
worldObj.spawnEntityInWorld(entityLightningBolt);
}
}
}
}
ArrayList<BlockPos> getFenceNet()
{
this.height = 0;
boolean broken = false;
for(int i=getPos().getY()+2; i<worldObj.getHeight()-1; i++)
{
BlockPos pos = new BlockPos(getPos().getX(),i,getPos().getZ());
if(!broken && isFence(pos))
this.height++;
else if(!worldObj.isAirBlock(pos))
return null;
else
{
if(!broken)
broken=true;
}
}
ArrayList<BlockPos> openList = new ArrayList();
ArrayList<BlockPos> closedList = new ArrayList();
openList.add(getPos().add(0,height,0));
while(!openList.isEmpty() && closedList.size()<256)
{
BlockPos next = openList.get(0);
if(!closedList.contains(next) && isFence(next))
{
closedList.add(next);
openList.add(next.offset(EnumFacing.WEST));
openList.add(next.offset(EnumFacing.EAST));
openList.add(next.offset(EnumFacing.NORTH));
openList.add(next.offset(EnumFacing.SOUTH));
openList.add(next.offset(EnumFacing.UP));
}
openList.remove(0);
}
return closedList;
}
boolean isFence(BlockPos pos)
{
return Utils.isBlockAt(worldObj, pos, IEContent.blockMetalDecoration1, BlockTypes_MetalDecoration1.STEEL_FENCE.getMeta());
}
@Override
public void readCustomNBT(NBTTagCompound nbt, boolean descPacket)
{
super.readCustomNBT(nbt, descPacket);
energyStorage.readFromNBT(nbt);
}
@Override
public void writeCustomNBT(NBTTagCompound nbt, boolean descPacket)
{
super.writeCustomNBT(nbt, descPacket);
energyStorage.writeToNBT(nbt);
}
@Override
public float[] getBlockBounds()
{
if(pos==22)
return new float[]{-.125f,0,-.125f,1.125f,1,1.125f};
if(pos%9==4 || (pos<18&&pos%9%2==1))
return new float[]{0,0,0,1,1,1};
if(pos<9)
return new float[]{0, 0, 0, 1, .5f, 1};
float xMin = 0;
float xMax = 1;
float yMin = 0;
float yMax = 1;
float zMin = 0;
float zMax = 1;
if(pos%9==0||pos%9==2||pos%9==6||pos%9==8)
{
if(pos < 18)
{
yMin = -.5f;
yMax = 1.25f;
xMin = (facing.getAxis() == Axis.X ? (pos%9 > 2 ^ facing == EnumFacing.EAST) : (pos % 3 == 2 ^ facing == EnumFacing.NORTH)) ? .8125f : .4375f;
xMax = (facing.getAxis() == Axis.X ? (pos%9 < 3 ^ facing == EnumFacing.EAST) : (pos % 3 == 0 ^ facing == EnumFacing.NORTH)) ? .1875f : .5625f;
zMin = (facing.getAxis() == Axis.X ? (pos % 3 == 2 ^ facing == EnumFacing.EAST) : (pos%9 < 3 ^ facing == EnumFacing.NORTH)) ? .8125f : .4375f;
zMax = (facing.getAxis() == Axis.X ? (pos % 3 == 0 ^ facing == EnumFacing.EAST) : (pos%9 > 2 ^ facing == EnumFacing.NORTH)) ? .1875f : .5625f;
}
else
{
yMin = .25f;
yMax = .75f;
xMin = (facing.getAxis() == Axis.X ? (pos%9 > 2 ^ facing == EnumFacing.EAST) : (pos % 3 == 2 ^ facing == EnumFacing.NORTH)) ? 1 : .625f;
xMax = (facing.getAxis() == Axis.X ? (pos%9 < 3 ^ facing == EnumFacing.EAST) : (pos % 3 == 0 ^ facing == EnumFacing.NORTH)) ? 0 : .375f;
zMin = (facing.getAxis() == Axis.X ? (pos % 3 == 2 ^ facing == EnumFacing.EAST) : (pos%9 < 3 ^ facing == EnumFacing.NORTH)) ? 1 : .625f;
zMax = (facing.getAxis() == Axis.X ? (pos % 3 == 0 ^ facing == EnumFacing.EAST) : (pos%9 > 2 ^ facing == EnumFacing.NORTH)) ? 0 : .375f;
}
}
else if(pos>17)
{
yMin = .25f;
yMax = .75f;
xMin = offset[0]<0?.375f:0;
xMax = offset[0]>0?.625f:1;
zMin = offset[2]<0?.375f:0;
zMax = offset[2]>0?.625f:1;
}
return new float[]{xMin, yMin, zMin, xMax, yMax, zMax};
}
@Override
public ItemStack getOriginalBlock()
{
if(pos<0)
return null;
ItemStack s = null;
try{
s = MultiblockLightningrod.instance.getStructureManual()[pos/9][pos%9/3][pos%3];
}catch(Exception e){e.printStackTrace();}
return s!=null?s.copy():null;
}
@Override
public void disassemble()
{
super.invalidate();
if(formed && !worldObj.isRemote)
{
BlockPos startPos = this.getPos().add(-offset[0],-offset[1],-offset[2]);
if(!(offset[0]==0&&offset[1]==0&&offset[2]==0) && !(worldObj.getTileEntity(startPos) instanceof TileEntityLightningrod))
return;
for(int yy=-1;yy<=1;yy++)
for(int xx=-1;xx<=1;xx++)
for(int zz=-1;zz<=1;zz++)
{
ItemStack s = null;
TileEntity te = worldObj.getTileEntity(startPos.add(xx, yy, zz));
if(te instanceof TileEntityLightningrod)
{
s = ((TileEntityLightningrod)te).getOriginalBlock();
((TileEntityLightningrod)te).formed=false;
}
if(startPos.add(xx, yy, zz).equals(getPos()))
s = this.getOriginalBlock();
if(s!=null && Block.getBlockFromItem(s.getItem())!=null)
{
if(startPos.add(xx, yy, zz).equals(getPos()))
worldObj.spawnEntityInWorld(new EntityItem(worldObj, getPos().getX()+.5,getPos().getY()+.5,getPos().getZ()+.5, s));
else
{
if(Block.getBlockFromItem(s.getItem())==IEContent.blockMetalMultiblock)
worldObj.setBlockToAir(startPos.add(xx, yy, zz));
worldObj.setBlockState(startPos.add(xx, yy, zz), Block.getBlockFromItem(s.getItem()).getStateFromMeta(s.getItemDamage()));
}
}
}
}
}
@Override
protected IFluidTank[] getAccessibleFluidTanks(EnumFacing side)
{
return new IFluidTank[0];
}
@Override
protected boolean canFillTankFrom(int iTank, EnumFacing side, FluidStack resource)
{
return false;
}
@Override
protected boolean canDrainTankFrom(int iTank, EnumFacing side)
{
return false;
}
@SideOnly(Side.CLIENT)
private AxisAlignedBB renderAABB;
@Override
@SideOnly(Side.CLIENT)
public AxisAlignedBB getRenderBoundingBox()
{
if(renderAABB==null)
if(pos==4)
renderAABB = new AxisAlignedBB(getPos().add(-1,0,-1), getPos().add(2,5,2));
else
renderAABB = new AxisAlignedBB(getPos(),getPos());
return renderAABB;
}
@Override
@SideOnly(Side.CLIENT)
public double getMaxRenderDistanceSquared()
{
return super.getMaxRenderDistanceSquared()* IEConfig.increasedTileRenderdistance;
}
@Override
public int extractEnergy(@Nullable EnumFacing from, int energy, boolean simulate)
{
if(pos!=10&&pos!=12&&pos!=14&pos!=16)
return 0;
TileEntityLightningrod master = master();
return master==null?0:master.energyStorage.extractEnergy(energy, simulate);
}
@Override
public int getEnergyStored(@Nullable EnumFacing from)
{
TileEntityLightningrod master = master();
return master==null?0:master.energyStorage.getEnergyStored();
}
@Override
public int getMaxEnergyStored(@Nullable EnumFacing from)
{
TileEntityLightningrod master = master();
return master==null?0:master.energyStorage.getMaxEnergyStored();
}
@Override
public boolean canConnectEnergy(@Nullable EnumFacing from)
{
return pos==10||pos==12||pos==14||pos==16;
}
}