import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.block.Block;
import net.minecraft.entity.Entity;
import net.minecraft.entity.IProjectile;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.util.Vec3;
import net.minecraft.world.World;
import java.util.List;
public abstract class EntityCustomThrowable extends Entity implements IProjectile{
public int throwableShake;
public Entity ignoreEntity;
protected boolean inGround;
protected EntityPlayer thrower;
private int xTile = -1;
private int yTile = -1;
private int zTile = -1;
private Block inTile;
private String throwerName;
private int ticksInGround;
private int ticksInAir;
private int ignoreTime;
public EntityCustomThrowable(World worldIn){
super(worldIn);
}
public EntityCustomThrowable(World worldIn, double x, double y, double z){
this(worldIn);
setPosition(x, y, z);
}
public EntityCustomThrowable(World worldIn, EntityPlayer throwerIn){
this(worldIn, throwerIn.posX, throwerIn.posY + throwerIn.getEyeHeight() - 0.10000000149011612D, throwerIn.posZ);
thrower = throwerIn;
}
@Override
protected void entityInit(){
setSize(0.25f, 0.25f);
renderDistanceWeight = 10.0D;
}
public void throwEntity(Entity entityThrower, float rotationYawIn, float rotationPitchIn, float pitchOffset, float velocity, float inaccuracy){
float f = -net.minecraft.util.MathHelper.sin(rotationYawIn / 180.0F * (float)Math.PI) * net.minecraft.util.MathHelper.cos(rotationPitchIn / 180.0F * (float)Math.PI);
float f1 = net.minecraft.util.MathHelper.cos(rotationYawIn / 180.0F * (float)Math.PI) * net.minecraft.util.MathHelper.cos(rotationPitchIn / 180.0F * (float)Math.PI);
float f2 = -net.minecraft.util.MathHelper.sin((rotationPitchIn + pitchOffset) / 180.0F * (float)Math.PI);
setThrowableHeading(f, f2, f1, velocity, inaccuracy);
motionX += entityThrower.motionX;
motionZ += entityThrower.motionZ;
if(!entityThrower.onGround){
motionY += entityThrower.motionY;
}
}
@Override
public void setThrowableHeading(double x, double y, double z, float velocity, float inaccuracy){
float f = (float)Math.sqrt((double)(x * x + y * y + z * z));
x /= (double)f;
y /= (double)f;
z /= (double)f;
x += rand.nextGaussian() * 0.007499999832361937 * (double)inaccuracy;
y += rand.nextGaussian() * 0.007499999832361937 * (double)inaccuracy;
z += rand.nextGaussian() * 0.007499999832361937 * (double)inaccuracy;
motionX = x *= (double)velocity;
motionY = y *= (double)velocity;
motionZ = z *= (double)velocity;
float f1 = (float)Math.sqrt((double)(x * x + z * z));
rotationYaw = (float)(Math.atan2((double)x, (double)z) * 57.29577951308232);
rotationPitch = (float)(Math.atan2((double)y, (double)f1) * 57.29577951308232);
prevRotationYaw = rotationYaw;
prevRotationPitch = rotationPitch;
ticksInGround = 0;
}
@Override
@SideOnly(value = Side.CLIENT)
public void setVelocity(double x, double y, double z){
motionX = x;
motionY = y;
motionZ = z;
if(prevRotationPitch == 0.0f && prevRotationYaw == 0.0f){
float f = (float)Math.sqrt((double)(x * x + z * z));
rotationYaw = (float)(Math.atan2((double)x, (double)z) * 57.29577951308232);
rotationPitch = (float)(Math.atan2((double)y, (double)f) * 57.29577951308232);
prevRotationYaw = rotationYaw;
prevRotationPitch = rotationPitch;
}
}
@Override
public void onUpdate(){
lastTickPosX = posX;
lastTickPosY = posY;
lastTickPosZ = posZ;
super.onUpdate();
if(throwableShake > 0){
--throwableShake;
}
if(inGround){
if(worldObj.getBlock(xTile, yTile, zTile) == inTile){
++ticksInGround;
if(ticksInGround == 1200){
setDead();
}
return;
}
inGround = false;
motionX *= (double)(rand.nextFloat() * 0.2f);
motionY *= (double)(rand.nextFloat() * 0.2f);
motionZ *= (double)(rand.nextFloat() * 0.2f);
ticksInGround = 0;
ticksInAir = 0;
}else{
++ticksInAir;
}
Vec3 posVec = Vec3.createVectorHelper(posX, posY, posZ);
Vec3 nextPosVec = Vec3.createVectorHelper(posX + motionX, posY + motionY, posZ + motionZ);
MovingObjectPosition rayTraceResult = worldObj.func_147447_a(posVec, nextPosVec, false, true, false);
posVec = Vec3.createVectorHelper(posX, posY, posZ);
nextPosVec = Vec3.createVectorHelper(posX + motionX, posY + motionY, posZ + motionZ);
if(rayTraceResult != null){
nextPosVec = Vec3.createVectorHelper(rayTraceResult.hitVec.xCoord, rayTraceResult.hitVec.yCoord, rayTraceResult.hitVec.zCoord);
}
Entity entity = null;
List list = worldObj.getEntitiesWithinAABBExcludingEntity((Entity)this, boundingBox.expand(motionX, motionY, motionZ).expand(1.0, 1.0, 1.0));
double distance = 0.0;
boolean flag = false;
for(int i = 0; i < list.size(); ++i){
double d1;
Entity entity1 = (Entity)list.get(i);
if(!entity1.canBeCollidedWith()) continue;
if(entity1 == ignoreEntity){
flag = true;
continue;
}
if(thrower != null && ticksExisted < 2 && ignoreEntity == null){
ignoreEntity = entity1;
flag = true;
continue;
}
flag = false;
AxisAlignedBB boundingBox = entity1.boundingBox.expand(0.3, 0.3, 0.3);
MovingObjectPosition result = boundingBox.calculateIntercept(posVec, nextPosVec);
if(result == null || !((d1 = posVec.squareDistanceTo(result.hitVec)) < distance) && distance != 0.0)
continue;
entity = entity1;
distance = d1;
}
if(ignoreEntity != null){
if(flag){
ignoreTime = 2;
}else if(ignoreTime-- <= 0){
ignoreEntity = null;
}
}
if(entity != null){
rayTraceResult = new MovingObjectPosition(entity);
}
if(rayTraceResult != null && onImpact(rayTraceResult)){
return;
}
posX += motionX;
posY += motionY;
posZ += motionZ;
float f = (float)Math.sqrt((double)(motionX * motionX + motionZ * motionZ));
rotationYaw = (float)(Math.atan2((double)motionX, (double)motionZ) * 57.29577951308232);
rotationPitch = (float)(Math.atan2((double)motionY, (double)f) * 57.29577951308232);
while(rotationPitch - prevRotationPitch < -180.0f){
prevRotationPitch -= 360.0f;
}
while(rotationPitch - prevRotationPitch >= 180.0f){
prevRotationPitch += 360.0f;
}
while(rotationYaw - prevRotationYaw < -180.0f){
prevRotationYaw -= 360.0f;
}
while(rotationYaw - prevRotationYaw >= 180.0f){
prevRotationYaw += 360.0f;
}
rotationPitch = prevRotationPitch + (rotationPitch - prevRotationPitch) * 0.2f;
rotationYaw = prevRotationYaw + (rotationYaw - prevRotationYaw) * 0.2f;
float f1 = 0.99f;
float f2 = getGravityVelocity();
if(isInWater()){
for(int j = 0; j < 4; ++j){
float f3 = 0.25f;
worldObj.spawnParticle("bubble", posX - motionX * 0.25, posY - motionY * 0.25, posZ - motionZ * 0.25, motionX, motionY, motionZ);
}
f1 = 0.8f;
}
motionX *= (double)f1;
motionY *= (double)f1;
motionZ *= (double)f1;
motionY -= (double)f2;
setPosition(posX, posY, posZ);
}
protected float getGravityVelocity(){
return 0.03f;
}
protected abstract boolean onImpact(MovingObjectPosition object);
@Override
public void writeEntityToNBT(NBTTagCompound compound){
compound.setInteger("xTile", xTile);
compound.setInteger("yTile", yTile);
compound.setInteger("zTile", zTile);
compound.setShort("inTile", (short)Block.getIdFromBlock(inTile));
compound.setByte("shake", (byte)throwableShake);
compound.setByte("inGround", (byte)(inGround ? 1 : 0));
if((throwerName == null || throwerName.isEmpty()) && thrower instanceof EntityPlayer){
throwerName = thrower.getCommandSenderName();
}
compound.setString("ownerName", throwerName == null ? "" : throwerName);
}
@Override
public void readEntityFromNBT(NBTTagCompound compound){
xTile = compound.getInteger("xTile");
yTile = compound.getInteger("yTile");
zTile = compound.getInteger("zTile");
inTile = compound.hasKey("inTile", 8) ? Block.getBlockFromName((String)compound.getString("inTile")) : Block.getBlockById((int)(compound.getByte("inTile") & 255));
throwableShake = compound.getByte("shake") & 255;
inGround = compound.getByte("inGround") == 1;
thrower = null;
throwerName = compound.getString("ownerName");
if(throwerName.isEmpty()){
throwerName = null;
}
thrower = getThrower();
}
public EntityPlayer getThrower(){
if(thrower == null && throwerName != null && !throwerName.isEmpty()){
thrower = worldObj.getPlayerEntityByName(throwerName);
}
return thrower;
}
public double getMotionSpeed(){
return Math.sqrt(Math.pow(motionX, 2.0) + Math.pow(motionY, 2.0) + Math.pow(motionZ, 2.0));
}
}