001 package net.minecraft.src; 002 003 import cpw.mods.fml.common.Side; 004 import cpw.mods.fml.common.asm.SideOnly; 005 import java.util.Iterator; 006 import java.util.List; 007 008 public abstract class EntityThrowable extends Entity 009 { 010 private int xTile = -1; 011 private int yTile = -1; 012 private int zTile = -1; 013 private int inTile = 0; 014 protected boolean inGround = false; 015 public int throwableShake = 0; 016 017 /** 018 * Is the entity that throws this 'thing' (snowball, ender pearl, eye of ender or potion) 019 */ 020 protected EntityLiving thrower; 021 private int ticksInGround; 022 private int ticksInAir = 0; 023 024 public EntityThrowable(World par1World) 025 { 026 super(par1World); 027 this.setSize(0.25F, 0.25F); 028 } 029 030 protected void entityInit() {} 031 032 @SideOnly(Side.CLIENT) 033 034 /** 035 * Checks if the entity is in range to render by using the past in distance and comparing it to its average edge 036 * length * 64 * renderDistanceWeight Args: distance 037 */ 038 public boolean isInRangeToRenderDist(double par1) 039 { 040 double var3 = this.boundingBox.getAverageEdgeLength() * 4.0D; 041 var3 *= 64.0D; 042 return par1 < var3 * var3; 043 } 044 045 public EntityThrowable(World par1World, EntityLiving par2EntityLiving) 046 { 047 super(par1World); 048 this.thrower = par2EntityLiving; 049 this.setSize(0.25F, 0.25F); 050 this.setLocationAndAngles(par2EntityLiving.posX, par2EntityLiving.posY + (double)par2EntityLiving.getEyeHeight(), par2EntityLiving.posZ, par2EntityLiving.rotationYaw, par2EntityLiving.rotationPitch); 051 this.posX -= (double)(MathHelper.cos(this.rotationYaw / 180.0F * (float)Math.PI) * 0.16F); 052 this.posY -= 0.10000000149011612D; 053 this.posZ -= (double)(MathHelper.sin(this.rotationYaw / 180.0F * (float)Math.PI) * 0.16F); 054 this.setPosition(this.posX, this.posY, this.posZ); 055 this.yOffset = 0.0F; 056 float var3 = 0.4F; 057 this.motionX = (double)(-MathHelper.sin(this.rotationYaw / 180.0F * (float)Math.PI) * MathHelper.cos(this.rotationPitch / 180.0F * (float)Math.PI) * var3); 058 this.motionZ = (double)(MathHelper.cos(this.rotationYaw / 180.0F * (float)Math.PI) * MathHelper.cos(this.rotationPitch / 180.0F * (float)Math.PI) * var3); 059 this.motionY = (double)(-MathHelper.sin((this.rotationPitch + this.func_70183_g()) / 180.0F * (float)Math.PI) * var3); 060 this.setThrowableHeading(this.motionX, this.motionY, this.motionZ, this.func_70182_d(), 1.0F); 061 } 062 063 public EntityThrowable(World par1World, double par2, double par4, double par6) 064 { 065 super(par1World); 066 this.ticksInGround = 0; 067 this.setSize(0.25F, 0.25F); 068 this.setPosition(par2, par4, par6); 069 this.yOffset = 0.0F; 070 } 071 072 protected float func_70182_d() 073 { 074 return 1.5F; 075 } 076 077 protected float func_70183_g() 078 { 079 return 0.0F; 080 } 081 082 /** 083 * Similar to setArrowHeading, it's point the throwable entity to a x, y, z direction. 084 */ 085 public void setThrowableHeading(double par1, double par3, double par5, float par7, float par8) 086 { 087 float var9 = MathHelper.sqrt_double(par1 * par1 + par3 * par3 + par5 * par5); 088 par1 /= (double)var9; 089 par3 /= (double)var9; 090 par5 /= (double)var9; 091 par1 += this.rand.nextGaussian() * 0.007499999832361937D * (double)par8; 092 par3 += this.rand.nextGaussian() * 0.007499999832361937D * (double)par8; 093 par5 += this.rand.nextGaussian() * 0.007499999832361937D * (double)par8; 094 par1 *= (double)par7; 095 par3 *= (double)par7; 096 par5 *= (double)par7; 097 this.motionX = par1; 098 this.motionY = par3; 099 this.motionZ = par5; 100 float var10 = MathHelper.sqrt_double(par1 * par1 + par5 * par5); 101 this.prevRotationYaw = this.rotationYaw = (float)(Math.atan2(par1, par5) * 180.0D / Math.PI); 102 this.prevRotationPitch = this.rotationPitch = (float)(Math.atan2(par3, (double)var10) * 180.0D / Math.PI); 103 this.ticksInGround = 0; 104 } 105 106 @SideOnly(Side.CLIENT) 107 108 /** 109 * Sets the velocity to the args. Args: x, y, z 110 */ 111 public void setVelocity(double par1, double par3, double par5) 112 { 113 this.motionX = par1; 114 this.motionY = par3; 115 this.motionZ = par5; 116 117 if (this.prevRotationPitch == 0.0F && this.prevRotationYaw == 0.0F) 118 { 119 float var7 = MathHelper.sqrt_double(par1 * par1 + par5 * par5); 120 this.prevRotationYaw = this.rotationYaw = (float)(Math.atan2(par1, par5) * 180.0D / Math.PI); 121 this.prevRotationPitch = this.rotationPitch = (float)(Math.atan2(par3, (double)var7) * 180.0D / Math.PI); 122 } 123 } 124 125 /** 126 * Called to update the entity's position/logic. 127 */ 128 public void onUpdate() 129 { 130 this.lastTickPosX = this.posX; 131 this.lastTickPosY = this.posY; 132 this.lastTickPosZ = this.posZ; 133 super.onUpdate(); 134 135 if (this.throwableShake > 0) 136 { 137 --this.throwableShake; 138 } 139 140 if (this.inGround) 141 { 142 int var1 = this.worldObj.getBlockId(this.xTile, this.yTile, this.zTile); 143 144 if (var1 == this.inTile) 145 { 146 ++this.ticksInGround; 147 148 if (this.ticksInGround == 1200) 149 { 150 this.setDead(); 151 } 152 153 return; 154 } 155 156 this.inGround = false; 157 this.motionX *= (double)(this.rand.nextFloat() * 0.2F); 158 this.motionY *= (double)(this.rand.nextFloat() * 0.2F); 159 this.motionZ *= (double)(this.rand.nextFloat() * 0.2F); 160 this.ticksInGround = 0; 161 this.ticksInAir = 0; 162 } 163 else 164 { 165 ++this.ticksInAir; 166 } 167 168 Vec3 var15 = Vec3.getVec3Pool().getVecFromPool(this.posX, this.posY, this.posZ); 169 Vec3 var2 = Vec3.getVec3Pool().getVecFromPool(this.posX + this.motionX, this.posY + this.motionY, this.posZ + this.motionZ); 170 MovingObjectPosition var3 = this.worldObj.rayTraceBlocks(var15, var2); 171 var15 = Vec3.getVec3Pool().getVecFromPool(this.posX, this.posY, this.posZ); 172 var2 = Vec3.getVec3Pool().getVecFromPool(this.posX + this.motionX, this.posY + this.motionY, this.posZ + this.motionZ); 173 174 if (var3 != null) 175 { 176 var2 = Vec3.getVec3Pool().getVecFromPool(var3.hitVec.xCoord, var3.hitVec.yCoord, var3.hitVec.zCoord); 177 } 178 179 if (!this.worldObj.isRemote) 180 { 181 Entity var4 = null; 182 List var5 = this.worldObj.getEntitiesWithinAABBExcludingEntity(this, this.boundingBox.addCoord(this.motionX, this.motionY, this.motionZ).expand(1.0D, 1.0D, 1.0D)); 183 double var6 = 0.0D; 184 Iterator var8 = var5.iterator(); 185 186 while (var8.hasNext()) 187 { 188 Entity var9 = (Entity)var8.next(); 189 190 if (var9.canBeCollidedWith() && (var9 != this.thrower || this.ticksInAir >= 5)) 191 { 192 float var10 = 0.3F; 193 AxisAlignedBB var11 = var9.boundingBox.expand((double)var10, (double)var10, (double)var10); 194 MovingObjectPosition var12 = var11.calculateIntercept(var15, var2); 195 196 if (var12 != null) 197 { 198 double var13 = var15.distanceTo(var12.hitVec); 199 200 if (var13 < var6 || var6 == 0.0D) 201 { 202 var4 = var9; 203 var6 = var13; 204 } 205 } 206 } 207 } 208 209 if (var4 != null) 210 { 211 var3 = new MovingObjectPosition(var4); 212 } 213 } 214 215 if (var3 != null) 216 { 217 this.onImpact(var3); 218 } 219 220 this.posX += this.motionX; 221 this.posY += this.motionY; 222 this.posZ += this.motionZ; 223 float var16 = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ); 224 this.rotationYaw = (float)(Math.atan2(this.motionX, this.motionZ) * 180.0D / Math.PI); 225 226 for (this.rotationPitch = (float)(Math.atan2(this.motionY, (double)var16) * 180.0D / Math.PI); this.rotationPitch - this.prevRotationPitch < -180.0F; this.prevRotationPitch -= 360.0F) 227 { 228 ; 229 } 230 231 while (this.rotationPitch - this.prevRotationPitch >= 180.0F) 232 { 233 this.prevRotationPitch += 360.0F; 234 } 235 236 while (this.rotationYaw - this.prevRotationYaw < -180.0F) 237 { 238 this.prevRotationYaw -= 360.0F; 239 } 240 241 while (this.rotationYaw - this.prevRotationYaw >= 180.0F) 242 { 243 this.prevRotationYaw += 360.0F; 244 } 245 246 this.rotationPitch = this.prevRotationPitch + (this.rotationPitch - this.prevRotationPitch) * 0.2F; 247 this.rotationYaw = this.prevRotationYaw + (this.rotationYaw - this.prevRotationYaw) * 0.2F; 248 float var17 = 0.99F; 249 float var18 = this.getGravityVelocity(); 250 251 if (this.isInWater()) 252 { 253 for (int var7 = 0; var7 < 4; ++var7) 254 { 255 float var19 = 0.25F; 256 this.worldObj.spawnParticle("bubble", this.posX - this.motionX * (double)var19, this.posY - this.motionY * (double)var19, this.posZ - this.motionZ * (double)var19, this.motionX, this.motionY, this.motionZ); 257 } 258 259 var17 = 0.8F; 260 } 261 262 this.motionX *= (double)var17; 263 this.motionY *= (double)var17; 264 this.motionZ *= (double)var17; 265 this.motionY -= (double)var18; 266 this.setPosition(this.posX, this.posY, this.posZ); 267 } 268 269 /** 270 * Gets the amount of gravity to apply to the thrown entity with each tick. 271 */ 272 protected float getGravityVelocity() 273 { 274 return 0.03F; 275 } 276 277 /** 278 * Called when this EntityThrowable hits a block or entity. 279 */ 280 protected abstract void onImpact(MovingObjectPosition var1); 281 282 /** 283 * (abstract) Protected helper method to write subclass entity data to NBT. 284 */ 285 public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound) 286 { 287 par1NBTTagCompound.setShort("xTile", (short)this.xTile); 288 par1NBTTagCompound.setShort("yTile", (short)this.yTile); 289 par1NBTTagCompound.setShort("zTile", (short)this.zTile); 290 par1NBTTagCompound.setByte("inTile", (byte)this.inTile); 291 par1NBTTagCompound.setByte("shake", (byte)this.throwableShake); 292 par1NBTTagCompound.setByte("inGround", (byte)(this.inGround ? 1 : 0)); 293 } 294 295 /** 296 * (abstract) Protected helper method to read subclass entity data from NBT. 297 */ 298 public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound) 299 { 300 this.xTile = par1NBTTagCompound.getShort("xTile"); 301 this.yTile = par1NBTTagCompound.getShort("yTile"); 302 this.zTile = par1NBTTagCompound.getShort("zTile"); 303 this.inTile = par1NBTTagCompound.getByte("inTile") & 255; 304 this.throwableShake = par1NBTTagCompound.getByte("shake") & 255; 305 this.inGround = par1NBTTagCompound.getByte("inGround") == 1; 306 } 307 308 @SideOnly(Side.CLIENT) 309 public float getShadowSize() 310 { 311 return 0.0F; 312 } 313 }