package blusunrize.immersiveengineering.common.blocks.metal;
import blusunrize.immersiveengineering.api.energy.wires.IImmersiveConnectable;
import blusunrize.immersiveengineering.api.energy.wires.ImmersiveNetHandler.Connection;
import blusunrize.immersiveengineering.api.energy.wires.TileEntityImmersiveConnectable;
import blusunrize.immersiveengineering.client.models.IOBJModelCallback;
import blusunrize.immersiveengineering.common.blocks.IEBlockInterfaces.IAdvancedCollisionBounds;
import blusunrize.immersiveengineering.common.blocks.IEBlockInterfaces.IDirectionalTile;
import blusunrize.immersiveengineering.common.util.IEDamageSources;
import blusunrize.immersiveengineering.common.util.Utils;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.inventory.EntityEquipmentSlot;
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.EnumFacing.AxisDirection;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class TileEntityRazorWire extends TileEntityImmersiveConnectable implements IDirectionalTile, IAdvancedCollisionBounds, IOBJModelCallback<IBlockState>
{
public EnumFacing facing = EnumFacing.NORTH;
@Override
public void readCustomNBT(NBTTagCompound nbt, boolean descPacket)
{
super.readCustomNBT(nbt, descPacket);
facing = EnumFacing.getFront(nbt.getInteger("facing"));
}
@Override
public void writeCustomNBT(NBTTagCompound nbt, boolean descPacket)
{
super.writeCustomNBT(nbt, descPacket);
nbt.setInteger("facing",facing.ordinal());
}
@Override
public EnumFacing getFacing()
{
return facing;
}
@Override
public void setFacing(EnumFacing facing)
{
this.facing = facing;
}
@Override
public int getFacingLimitation()
{
return 2;
}
@Override
public boolean mirrorFacingOnPlacement(EntityLivingBase placer)
{
return false;
}
@Override
public boolean canHammerRotate(EnumFacing side, float hitX, float hitY, float hitZ, EntityLivingBase entity)
{
return true;
}
@Override
public boolean canRotate(EnumFacing axis)
{
return true;
}
@Override
public void onEntityCollision(World world, Entity entity)
{
if(entity instanceof EntityLivingBase)
{
entity.motionX *= 0.2D;
entity.motionZ *= 0.2D;
int protection = (((EntityLivingBase)entity).getItemStackFromSlot(EntityEquipmentSlot.FEET)!=null?1:0)+(((EntityLivingBase)entity).getItemStackFromSlot(EntityEquipmentSlot.LEGS)!=null?1:0);
float dmg = protection==2?.5f:protection==1?1:1.5f;
entity.attackEntityFrom(IEDamageSources.razorWire, dmg);
}
}
@Override
public float[] getBlockBounds()
{
return null;
}
@Override
public List<AxisAlignedBB> getAdvancedColisionBounds()
{
boolean wallL = renderWall(true);
boolean wallR = renderWall(false);
if(!isOnGround() || !(wallL||wallR))
return Collections.singletonList(null);
List<AxisAlignedBB> list = new ArrayList<>(wallL&&wallR?2:1);
if(wallL)
list.add(new AxisAlignedBB(facing==EnumFacing.SOUTH?.8125:0,0,facing==EnumFacing.WEST?.8125:0, facing==EnumFacing.NORTH?.1875:1,1,facing==EnumFacing.EAST?.1875:1).offset(getPos()));
if(wallR)
list.add(new AxisAlignedBB(facing==EnumFacing.NORTH?.8125:0,0,facing==EnumFacing.EAST?.8125:0, facing==EnumFacing.SOUTH?.1875:1,1,facing==EnumFacing.WEST?.1875:1).offset(getPos()));
return list;
}
private boolean renderWall(boolean left)
{
EnumFacing dir = left?facing.rotateY():facing.rotateYCCW();
BlockPos neighbourPos = getPos().offset(dir, -1);
if(!worldObj.isBlockLoaded(neighbourPos))
return true;
if(worldObj.getTileEntity(neighbourPos) instanceof TileEntityRazorWire)
return false;
IBlockState neighbour = worldObj.getBlockState(neighbourPos);
return !neighbour.isSideSolid(worldObj, neighbourPos, dir);
}
private boolean isOnGround()
{
BlockPos down = getPos().down();
return worldObj.getBlockState(down).isSideSolid(worldObj,down,EnumFacing.UP);
}
private boolean isStacked()
{
BlockPos down = getPos().down();
TileEntity te = worldObj.getTileEntity(down);
if(te instanceof TileEntityRazorWire)
return ((TileEntityRazorWire)te).isOnGround();
return false;
}
@SideOnly(Side.CLIENT)
@Override
public TextureAtlasSprite getTextureReplacement(IBlockState object, String material)
{
return null;
}
@SideOnly(Side.CLIENT)
@Override
public boolean shouldRenderGroup(IBlockState object, String group)
{
if(group==null)
return false;
boolean stack = isStacked();
if(!stack && !isOnGround())
return !group.startsWith("wood");
if(group.startsWith("wood") && !(group.endsWith("inverted")==stack))
return false;
if(group.startsWith("wood_left"))
return renderWall(true);
else if("wire_left".equals(group)||"barbs_left".equals(group))
return !renderWall(true);
else if(group.startsWith("wood_right"))
return renderWall(false);
else if("wire_right".equals(group)||"barbs_right".equals(group))
return !renderWall(false);
return true;
}
@SideOnly(Side.CLIENT)
@Override
public String getCacheKey(IBlockState object)
{
boolean stack = isStacked();
if(!stack && !isOnGround())
return "default";
return (renderWall(true)?"L":" ")+(renderWall(false)?"R":" ")+(stack?"_stack":"");
}
@Override
protected boolean canTakeLV()
{
return true;
}
@Override
public boolean isEnergyOutput()
{
return true;
}
@Override
public int outputEnergy(int amount, boolean simulate, int energyType)
{
if(amount>0)
{
if(!simulate)
{
int maxReach = amount/8;
int widthP = 0;
boolean connectP = true;
int widthN = 0;
boolean connectN = true;
EnumFacing dir = facing.rotateY();
if(dir.getAxisDirection()==AxisDirection.NEGATIVE)
dir = dir.getOpposite();
for(int i=1; i<=maxReach; i++)
{
BlockPos posP = getPos().offset(dir,i);
if(connectP && worldObj.isBlockLoaded(posP) && worldObj.getTileEntity(posP) instanceof TileEntityRazorWire)
widthP++;
else
connectP = false;
BlockPos posN = getPos().offset(dir,-i);
if(connectN && worldObj.isBlockLoaded(posN) && worldObj.getTileEntity(posN) instanceof TileEntityRazorWire)
widthN++;
else
connectN = false;
}
AxisAlignedBB aabb = new AxisAlignedBB(getPos().add(facing.getAxis()==Axis.Z?-widthN:0,0,facing.getAxis()==Axis.X?-widthN:0),getPos().add(facing.getAxis()==Axis.Z?1+widthP:1,1,facing.getAxis()==Axis.X?1+widthP:1));
List<EntityLivingBase> entities = worldObj.getEntitiesWithinAABB(EntityLivingBase.class, aabb);
for(EntityLivingBase ent : entities)
ent.attackEntityFrom(IEDamageSources.razorShock,2);
}
return 64;
}
return 0;
}
@Override
public Vec3d getRaytraceOffset(IImmersiveConnectable link)
{
return new Vec3d(.5,1.0625,.5);
}
@Override
public Vec3d getConnectionOffset(Connection con)
{
int xDif = (con==null||con.start==null||con.end==null)?0: (con.start.equals(Utils.toCC(this))&&con.end!=null)? con.end.getX()-getPos().getX(): (con.end.equals(Utils.toCC(this))&& con.start!=null)?con.start.getX()-getPos().getX(): 0;
int yDif = (con==null||con.start==null||con.end==null)?0: (con.start.equals(Utils.toCC(this))&&con.end!=null)? con.end.getY()-getPos().getY(): (con.end.equals(Utils.toCC(this))&& con.start!=null)?con.start.getY()-getPos().getY(): 0;
int zDif = (con==null||con.start==null||con.end==null)?0: (con.start.equals(Utils.toCC(this))&&con.end!=null)? con.end.getZ()-getPos().getZ(): (con.end.equals(Utils.toCC(this))&& con.start!=null)?con.start.getZ()-getPos().getZ(): 0;
boolean wallL = renderWall(true);
boolean wallR = renderWall(false);
if(!isOnGround() || !(wallL||wallR))
{
if(yDif>0)
return new Vec3d(facing.getFrontOffsetX()!=0?.5:xDif<0?.40625:.59375, .9375, facing.getFrontOffsetZ()!=0?.5:zDif<0?.40625:.59375);
else
{
boolean right = facing.rotateY().getAxisDirection().getOffset()==Math.copySign(1, facing.getFrontOffsetX()!=0?zDif:xDif);
int faceX = facing.getFrontOffsetX();
int faceZ = facing.getFrontOffsetZ();
return new Vec3d(faceX!=0?.5+(right?0:faceX*.1875):(xDif<0?0:1), .046875, faceZ!=0?.5+(right?0:faceZ*.1875):(zDif<0?0:1));
}
}
else
{
boolean wallN = facing==EnumFacing.NORTH||facing==EnumFacing.EAST?wallL:wallR;
return new Vec3d(facing.getFrontOffsetX()!=0?.5: xDif<0&&wallN?.125:.875, .9375, facing.getFrontOffsetZ()!=0?.5:zDif<0&&wallN?.125:.875);
}
}
}