// @Override
  @Override
  public void onUpdate() {
    super.onUpdate();

    if (this.prevRotationPitch == 0.0F && this.prevRotationYaw == 0.0F) {
      float f = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ);
      this.prevRotationYaw =
          this.rotationYaw = (float) (Math.atan2(this.motionX, this.motionZ) * 180.0D / Math.PI);
      // this.prevRotationPitch = this.rotationPitch = (float)(Math.atan2(this.motionY, (double)f) *
      // 180.0D / Math.PI);
    }

    Block block =
        this.worldObj.getBlock(this.field_145791_d, this.field_145792_e, this.field_145789_f);

    if (block.getMaterial() != Material.air) {
      block.setBlockBoundsBasedOnState(
          this.worldObj, this.field_145791_d, this.field_145792_e, this.field_145789_f);
      AxisAlignedBB axisalignedbb =
          block.getCollisionBoundingBoxFromPool(
              this.worldObj, this.field_145791_d, this.field_145792_e, this.field_145789_f);

      if (axisalignedbb != null
          && axisalignedbb.isVecInside(Vec3.createVectorHelper(this.posX, this.posY, this.posZ))) {
        this.inGround = true;
      }
    }

    if (this.arrowShake > 0) {
      --this.arrowShake;
    }

    if (this.inGround) {
      /*int j = this.worldObj.getBlockMetadata(this.field_145791_d, this.field_145792_e, this.field_145789_f);

      if (block == this.field_145790_g && j == this.inData)
      {
          ++this.ticksInGround;

          if (this.ticksInGround == 1200)
          {
              this.setDead();
          }
      }
      else
      {
          this.inGround = false;
          this.motionX *= (double)(this.rand.nextFloat() * 0.2F);
          this.motionY *= (double)(this.rand.nextFloat() * 0.2F);
          this.motionZ *= (double)(this.rand.nextFloat() * 0.2F);
          this.ticksInGround = 0;
          this.ticksInAir = 0;
      }*/

      if (!this.worldObj.isRemote) {
        this.worldObj.createExplosion(this, this.posX, this.posY, this.posZ, 2.5F, true);
        ExplosionChaos.burn(this.worldObj, (int) this.posX, (int) this.posY, (int) this.posZ, 10);
        ExplosionChaos.flameDeath(
            this.worldObj, (int) this.posX, (int) this.posY, (int) this.posZ, 20);
        ExplosionNukeGeneric.waste(
            this.worldObj, (int) this.posX, (int) this.posY, (int) this.posZ, 20);
        ExplosionChaos.poison(this.worldObj, (int) this.posX, (int) this.posY, (int) this.posZ, 20);
      }
      this.worldObj.spawnEntityInWorld(
          new EntityLightningBolt(this.worldObj, this.posX, this.posY, this.posZ));
      this.setDead();
    } else {
      ++this.ticksInAir;
      Vec3 vec31 = Vec3.createVectorHelper(this.posX, this.posY, this.posZ);
      Vec3 vec3 =
          Vec3.createVectorHelper(
              this.posX + this.motionX, this.posY + this.motionY, this.posZ + this.motionZ);
      MovingObjectPosition movingobjectposition =
          this.worldObj.func_147447_a(vec31, vec3, false, true, false);
      vec31 = Vec3.createVectorHelper(this.posX, this.posY, this.posZ);
      vec3 =
          Vec3.createVectorHelper(
              this.posX + this.motionX, this.posY + this.motionY, this.posZ + this.motionZ);

      if (movingobjectposition != null) {
        vec3 =
            Vec3.createVectorHelper(
                movingobjectposition.hitVec.xCoord,
                movingobjectposition.hitVec.yCoord,
                movingobjectposition.hitVec.zCoord);
      }

      Entity entity = null;
      List list =
          this.worldObj.getEntitiesWithinAABBExcludingEntity(
              this,
              this.boundingBox
                  .addCoord(this.motionX, this.motionY, this.motionZ)
                  .expand(1.0D, 1.0D, 1.0D));
      double d0 = 0.0D;
      int i;
      float f1;

      for (i = 0; i < list.size(); ++i) {
        Entity entity1 = (Entity) list.get(i);

        if (entity1.canBeCollidedWith()
            && (entity1 != this.shootingEntity || this.ticksInAir >= 5)) {
          f1 = 0.3F;
          AxisAlignedBB axisalignedbb1 = entity1.boundingBox.expand(f1, f1, f1);
          MovingObjectPosition movingobjectposition1 =
              axisalignedbb1.calculateIntercept(vec31, vec3);

          if (movingobjectposition1 != null) {
            double d1 = vec31.distanceTo(movingobjectposition1.hitVec);

            if (d1 < d0 || d0 == 0.0D) {
              entity = entity1;
              d0 = d1;
            }
          }
        }
      }

      if (entity != null) {
        movingobjectposition = new MovingObjectPosition(entity);
      }

      if (movingobjectposition != null
          && movingobjectposition.entityHit != null
          && movingobjectposition.entityHit instanceof EntityPlayer) {
        EntityPlayer entityplayer = (EntityPlayer) movingobjectposition.entityHit;

        if (entityplayer.capabilities.disableDamage
            || this.shootingEntity instanceof EntityPlayer
                && !((EntityPlayer) this.shootingEntity).canAttackPlayer(entityplayer)) {
          movingobjectposition = null;
        }
      }

      float f2;
      float f4;

      if (movingobjectposition != null) {
        if (movingobjectposition.entityHit != null) {
          f2 =
              MathHelper.sqrt_double(
                  this.motionX * this.motionX
                      + this.motionY * this.motionY
                      + this.motionZ * this.motionZ);
          int k = MathHelper.ceiling_double_int(f2 * this.damage);

          if (this.getIsCritical()) {
            k += this.rand.nextInt(k / 2 + 2);
          }

          DamageSource damagesource = null;

          if (this.shootingEntity == null) {
            damagesource = DamageSource.causeIndirectMagicDamage(this, this);
          } else {
            damagesource = DamageSource.causeIndirectMagicDamage(this, this);
          }

          if (this.isBurning() && !(movingobjectposition.entityHit instanceof EntityEnderman)) {
            movingobjectposition.entityHit.setFire(5);
          }

          if (movingobjectposition.entityHit.attackEntityFrom(damagesource, k)) {
            if (movingobjectposition.entityHit instanceof EntityLivingBase) {
              EntityLivingBase entitylivingbase = (EntityLivingBase) movingobjectposition.entityHit;

              if (!this.worldObj.isRemote) {
                entitylivingbase.setArrowCountInEntity(
                    entitylivingbase.getArrowCountInEntity() + 1);
              }

              if (this.knockbackStrength > 0) {
                f4 =
                    MathHelper.sqrt_double(
                        this.motionX * this.motionX + this.motionZ * this.motionZ);

                if (f4 > 0.0F) {
                  movingobjectposition.entityHit.addVelocity(
                      this.motionX * this.knockbackStrength * 0.6000000238418579D / f4,
                      0.1D,
                      this.motionZ * this.knockbackStrength * 0.6000000238418579D / f4);
                }
              }

              if (this.shootingEntity != null && this.shootingEntity instanceof EntityLivingBase) {
                EnchantmentHelper.func_151384_a(entitylivingbase, this.shootingEntity);
                EnchantmentHelper.func_151385_b(
                    (EntityLivingBase) this.shootingEntity, entitylivingbase);
              }

              if (this.shootingEntity != null
                  && movingobjectposition.entityHit != this.shootingEntity
                  && movingobjectposition.entityHit instanceof EntityPlayer
                  && this.shootingEntity instanceof EntityPlayerMP) {
                ((EntityPlayerMP) this.shootingEntity)
                    .playerNetServerHandler.sendPacket(new S2BPacketChangeGameState(6, 0.0F));
              }
            }

            if (!(movingobjectposition.entityHit instanceof EntityEnderman)) {
              if (!this.worldObj.isRemote) {
                this.worldObj.createExplosion(this, this.posX, this.posY, this.posZ, 2.5F, true);
              }
              this.setDead();
            }
          } else {
            this.motionX *= -0.10000000149011612D;
            this.motionY *= -0.10000000149011612D;
            this.motionZ *= -0.10000000149011612D;
            this.rotationYaw += 180.0F;
            this.prevRotationYaw += 180.0F;
            this.ticksInAir = 0;
          }
        } else {
          this.field_145791_d = movingobjectposition.blockX;
          this.field_145792_e = movingobjectposition.blockY;
          this.field_145789_f = movingobjectposition.blockZ;
          this.field_145790_g =
              this.worldObj.getBlock(this.field_145791_d, this.field_145792_e, this.field_145789_f);
          this.inData =
              this.worldObj.getBlockMetadata(
                  this.field_145791_d, this.field_145792_e, this.field_145789_f);
          this.motionX = ((float) (movingobjectposition.hitVec.xCoord - this.posX));
          this.motionY = ((float) (movingobjectposition.hitVec.yCoord - this.posY));
          this.motionZ = ((float) (movingobjectposition.hitVec.zCoord - this.posZ));
          f2 =
              MathHelper.sqrt_double(
                  this.motionX * this.motionX
                      + this.motionY * this.motionY
                      + this.motionZ * this.motionZ);
          this.posX -= this.motionX / f2 * 0.05000000074505806D;
          this.posY -= this.motionY / f2 * 0.05000000074505806D;
          this.posZ -= this.motionZ / f2 * 0.05000000074505806D;
          this.playSound("random.bowhit", 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F));
          this.inGround = true;
          this.arrowShake = 7;
          this.setIsCritical(false);

          if (this.field_145790_g.getMaterial() != Material.air) {
            this.field_145790_g.onEntityCollidedWithBlock(
                this.worldObj, this.field_145791_d, this.field_145792_e, this.field_145789_f, this);
          }
        }
      }

      if (true) {
        for (i = 0; i < 4; ++i) {
          this.worldObj.spawnParticle(
              "smoke",
              this.posX,
              this.posY,
              this.posZ,
              0,
              0,
              0 /*this.posX + this.motionX * (double)i / 4.0D, this.posY + this.motionY * (double)i / 4.0D, this.posZ + this.motionZ * (double)i / 4.0D, -this.motionX, -this.motionY + 0.2D, -this.motionZ*/);
        }
      }

      this.posX += this.motionX;
      this.posY += this.motionY;
      this.posZ += this.motionZ;
      f2 = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ);
      this.rotationYaw = (float) (Math.atan2(this.motionX, this.motionZ) * 180.0D / Math.PI);

      // for (this.rotationPitch = (float)(Math.atan2(this.motionY, (double)f2) * 180.0D / Math.PI);
      // this.rotationPitch - this.prevRotationPitch < -180.0F; this.prevRotationPitch -= 360.0F)
      {;
      }

      /*while (this.rotationPitch - this.prevRotationPitch >= 180.0F)
      {
          this.prevRotationPitch += 360.0F;
      }

      while (this.rotationYaw - this.prevRotationYaw < -180.0F)
      {
          this.prevRotationYaw -= 360.0F;
      }

      while (this.rotationYaw - this.prevRotationYaw >= 180.0F)
      {
          this.prevRotationYaw += 360.0F;
      }*/

      // this.rotationPitch = this.prevRotationPitch + (this.rotationPitch - this.prevRotationPitch)
      // * 0.2F;
      // this.rotationYaw = this.prevRotationYaw + (this.rotationYaw - this.prevRotationYaw) * 0.2F;
      float f3 = 0.99F;
      f1 = 0.05F;

      if (this.isInWater()) {
        for (int l = 0; l < 4; ++l) {
          f4 = 0.25F;
          this.worldObj.spawnParticle(
              "bubble",
              this.posX - this.motionX * f4,
              this.posY - this.motionY * f4,
              this.posZ - this.motionZ * f4,
              this.motionX,
              this.motionY,
              this.motionZ);
        }

        f3 = 0.8F;
      }

      if (this.isWet()) {
        this.extinguish();
      }

      this.motionX *= f3;
      this.motionY *= f3;
      this.motionZ *= f3;
      this.motionY -= gravity;
      this.setPosition(this.posX, this.posY, this.posZ);
      this.func_145775_I();
    }
  }
  /** Called to update the entity's position/logic. */
  public void onUpdate() {
    super.onUpdate();

    if (this.prevRotationPitch == 0.0F && this.prevRotationYaw == 0.0F) {
      float f = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ);
      this.prevRotationYaw =
          this.rotationYaw = (float) (Math.atan2(this.motionX, this.motionZ) * 180.0D / Math.PI);
      this.prevRotationPitch =
          this.rotationPitch = (float) (Math.atan2(this.motionY, (double) f) * 180.0D / Math.PI);
    }

    Block i = this.worldObj.getBlock(this.xTile, this.yTile, this.zTile);

    if (!i.equals(Blocks.air)) {
      i.setBlockBoundsBasedOnState(this.worldObj, this.xTile, this.yTile, this.zTile);
      AxisAlignedBB axisalignedbb =
          i.getCollisionBoundingBoxFromPool(this.worldObj, this.xTile, this.yTile, this.zTile);

      if (axisalignedbb != null
          && axisalignedbb.isVecInside(Vec3.createVectorHelper(this.posX, this.posY, this.posZ))) {
        this.inGround = true;
      }
    }

    if (this.arrowShake > 0) {
      --this.arrowShake;
    }

    if (this.inGround) {
      Block j = this.worldObj.getBlock(this.xTile, this.yTile, this.zTile);
      int k = this.worldObj.getBlockMetadata(this.xTile, this.yTile, this.zTile);

      if (j == this.inTile && k == this.inData) {
        ++this.ticksInGround;

        if (this.ticksInGround == 1200) {
          this.setDead();
        }
      } else {
        this.inGround = false;
        this.motionX *= (double) (this.rand.nextFloat() * 0.2F);
        this.motionY *= (double) (this.rand.nextFloat() * 0.2F);
        this.motionZ *= (double) (this.rand.nextFloat() * 0.2F);
        this.ticksInGround = 0;
        this.ticksInAir = 0;
      }
    } else {
      ++this.ticksInAir;
      Vec3 vec31 = Vec3.createVectorHelper(this.posX, this.posY, this.posZ);
      Vec3 vec3 =
          Vec3.createVectorHelper(
              this.posX + this.motionX, this.posY + this.motionY, this.posZ + this.motionZ);
      MovingObjectPosition movingobjectposition =
          this.worldObj.func_147447_a(vec31, vec3, false, true, false);
      vec31 = Vec3.createVectorHelper(this.posX, this.posY, this.posZ);
      vec3 =
          Vec3.createVectorHelper(
              this.posX + this.motionX, this.posY + this.motionY, this.posZ + this.motionZ);

      if (movingobjectposition != null) {
        vec31 =
            Vec3.createVectorHelper(
                movingobjectposition.hitVec.xCoord,
                movingobjectposition.hitVec.yCoord,
                movingobjectposition.hitVec.zCoord);
      }

      Entity entity = null;
      List list =
          this.worldObj.getEntitiesWithinAABBExcludingEntity(
              this,
              this.boundingBox
                  .addCoord(this.motionX, this.motionY, this.motionZ)
                  .expand(1.0D, 1.0D, 1.0D));
      double d0 = 0.0D;
      int l;
      float f1;

      for (l = 0; l < list.size(); ++l) {
        Entity entity1 = (Entity) list.get(l);

        if (entity1.canBeCollidedWith()
            && (entity1 != this.shootingEntity || this.ticksInAir >= 5)) {
          f1 = 0.3F;
          AxisAlignedBB axisalignedbb1 =
              entity1.boundingBox.expand((double) f1, (double) f1, (double) f1);
          MovingObjectPosition movingobjectposition1 =
              axisalignedbb1.calculateIntercept(vec3, vec31);

          if (movingobjectposition1 != null) {
            double d1 = vec3.distanceTo(movingobjectposition1.hitVec);

            if (d1 < d0 || d0 == 0.0D) {
              entity = entity1;
              d0 = d1;
            }
          }
        }
      }

      if (entity != null) {
        movingobjectposition = new MovingObjectPosition(entity);
      }

      if (movingobjectposition != null
          && movingobjectposition.entityHit != null
          && movingobjectposition.entityHit instanceof EntityPlayer) {
        EntityPlayer entityplayer = (EntityPlayer) movingobjectposition.entityHit;

        if (entityplayer.capabilities.disableDamage
            || this.shootingEntity instanceof EntityPlayer
                && !((EntityPlayer) this.shootingEntity).canAttackPlayer(entityplayer)) {
          movingobjectposition = null;
        }
      }

      float f2;
      float f3;

      if (movingobjectposition != null) {
        if (movingobjectposition.entityHit != null) {
          f2 =
              MathHelper.sqrt_double(
                  this.motionX * this.motionX
                      + this.motionY * this.motionY
                      + this.motionZ * this.motionZ);
          int i1 = MathHelper.ceiling_double_int((double) f2 * this.damage);

          if (this.getIsCritical()) {
            i1 += this.rand.nextInt(i1 / 2 + 2);
          }

          DamageSource damagesource = null;

          if (this.shootingEntity == null) {
            damagesource = mod_Rediscovered.causeParrowDamage(this, this);
          } else {
            damagesource = mod_Rediscovered.causeParrowDamage(this, this.shootingEntity);
          }

          if (this.isBurning() && !(movingobjectposition.entityHit instanceof EntityEnderman)) {
            movingobjectposition.entityHit.setFire(5);
          }

          if (movingobjectposition.entityHit.attackEntityFrom(damagesource, (float) i1)) {
            if (movingobjectposition.entityHit instanceof EntityLivingBase) {
              EntityLivingBase entitylivingbase = (EntityLivingBase) movingobjectposition.entityHit;

              if (!this.worldObj.isRemote) {
                entitylivingbase.setArrowCountInEntity(
                    entitylivingbase.getArrowCountInEntity() + 1);
              }

              if (this.knockbackStrength > 0) {
                f3 =
                    MathHelper.sqrt_double(
                        this.motionX * this.motionX + this.motionZ * this.motionZ);

                if (f3 > 0.0F) {
                  movingobjectposition.entityHit.addVelocity(
                      this.motionX
                          * (double) this.knockbackStrength
                          * 0.6000000238418579D
                          / (double) f3,
                      0.1D,
                      this.motionZ
                          * (double) this.knockbackStrength
                          * 0.6000000238418579D
                          / (double) f3);
                }
              }
            }

            this.playSound("random.bowhit", 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F));

            if (!(movingobjectposition.entityHit instanceof EntityEnderman)) {
              this.setDead();
            }
          } else {
            this.motionX *= -0.10000000149011612D;
            this.motionY *= -0.10000000149011612D;
            this.motionZ *= -0.10000000149011612D;
            this.rotationYaw += 180.0F;
            this.prevRotationYaw += 180.0F;
            this.ticksInAir = 0;
          }
        } else {
          this.xTile = movingobjectposition.blockX;
          this.yTile = movingobjectposition.blockY;
          this.zTile = movingobjectposition.blockZ;
          this.inTile = this.worldObj.getBlock(this.xTile, this.yTile, this.zTile);
          this.inData = this.worldObj.getBlockMetadata(this.xTile, this.yTile, this.zTile);
          this.motionX = (double) ((float) (movingobjectposition.hitVec.xCoord - this.posX));
          this.motionY = (double) ((float) (movingobjectposition.hitVec.yCoord - this.posY));
          this.motionZ = (double) ((float) (movingobjectposition.hitVec.zCoord - this.posZ));
          f2 =
              MathHelper.sqrt_double(
                  this.motionX * this.motionX
                      + this.motionY * this.motionY
                      + this.motionZ * this.motionZ);
          this.posX -= this.motionX / (double) f2 * 0.05000000074505806D;
          this.posY -= this.motionY / (double) f2 * 0.05000000074505806D;
          this.posZ -= this.motionZ / (double) f2 * 0.05000000074505806D;
          this.playSound("random.bowhit", 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F));
          this.inGround = true;
          this.arrowShake = 7;
          this.setIsCritical(false);

          if (!this.inTile.equals(Blocks.air)) {
            this.inTile.onEntityCollidedWithBlock(
                this.worldObj, this.xTile, this.yTile, this.zTile, this);
          }
        }
      }

      if (this.getIsCritical()) {
        for (l = 0; l < 4; ++l) {
          this.worldObj.spawnParticle(
              "crit",
              this.posX + this.motionX * (double) l / 4.0D,
              this.posY + this.motionY * (double) l / 4.0D,
              this.posZ + this.motionZ * (double) l / 4.0D,
              -this.motionX,
              -this.motionY + 0.2D,
              -this.motionZ);
        }
      }

      this.posX += this.motionX;
      this.posY += this.motionY;
      this.posZ += this.motionZ;
      f2 = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ);
      this.rotationYaw = (float) (Math.atan2(this.motionX, this.motionZ) * 180.0D / Math.PI);

      for (this.rotationPitch = (float) (Math.atan2(this.motionY, (double) f2) * 180.0D / Math.PI);
          this.rotationPitch - this.prevRotationPitch < -180.0F;
          this.prevRotationPitch -= 360.0F) {;
      }

      while (this.rotationPitch - this.prevRotationPitch >= 180.0F) {
        this.prevRotationPitch += 360.0F;
      }

      while (this.rotationYaw - this.prevRotationYaw < -180.0F) {
        this.prevRotationYaw -= 360.0F;
      }

      while (this.rotationYaw - this.prevRotationYaw >= 180.0F) {
        this.prevRotationYaw += 360.0F;
      }

      this.rotationPitch =
          this.prevRotationPitch + (this.rotationPitch - this.prevRotationPitch) * 0.2F;
      this.rotationYaw = this.prevRotationYaw + (this.rotationYaw - this.prevRotationYaw) * 0.2F;
      float f4 = 0.99F;
      f1 = 0.05F;

      if (this.isInWater()) {
        for (int j1 = 0; j1 < 4; ++j1) {
          f3 = 0.25F;
          this.worldObj.spawnParticle(
              "bubble",
              this.posX - this.motionX * (double) f3,
              this.posY - this.motionY * (double) f3,
              this.posZ - this.motionZ * (double) f3,
              this.motionX,
              this.motionY,
              this.motionZ);
        }

        f4 = 0.8F;
      }

      this.motionX *= (double) f4;
      this.motionY *= (double) f4;
      this.motionZ *= (double) f4;
      this.motionY -= (double) f1;
      this.setPosition(this.posX, this.posY, this.posZ);
      //            this.doBlockCollisions();
    }
  }
  /*
   * Tick毎に呼ばれる更新処理。
   * 速度の更新、衝突判定などをここで行う。
   */
  @Override
  public void onUpdate() {
    super.onUpdate();

    livingTimeCount++;

    // その1、爆発処理
    byte exp = this.isExploded();
    if (exp == 1) {
      this.setDead();
    } else if (exp > 1) {
      AMTLogger.debugInfo("current explode int :" + exp);
      this.worldObj.spawnParticle(
          "hugeexplosion",
          this.posX,
          this.posY + 1.0D,
          this.posZ,
          this.motionX,
          this.motionY,
          this.motionZ);
      exp--;
      this.setTimeCount(exp);
    }

    // その2、アクティブか否か
    if (livingTimeCount > 3 && !this.active) {
      this.active = true;
      this.setActive((byte) 1);
      this.playSound("defeatedcrow:knock", 0.5F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F));
    }

    boolean explode = false;

    // 以降、アクティブか否かで動作が変わる。
    if (this.active) {
      double dx = -(double) (MathHelper.sin(this.rotationYaw / 180.0F * (float) Math.PI));
      double dz = -(double) (MathHelper.cos(this.rotationYaw / 180.0F * (float) Math.PI));
      for (int i = 0; i < 4; ++i) {
        this.worldObj.spawnParticle(
            "crit",
            this.posX + dx,
            this.posY,
            this.posZ + dz,
            -this.motionX,
            -this.motionY + 0.2D,
            -this.motionZ);
      }
    }

    // 直前のパラメータと新パラメータを一致させているところ。
    // また、速度に応じてエンティティの向きを調整し、常に進行方向に前面が向くようにしている。
    if (this.prevRotationPitch == 0.0F && this.prevRotationYaw == 0.0F) {
      float f = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ);
      this.prevRotationYaw =
          this.rotationYaw = (float) (Math.atan2(this.motionX, this.motionZ) * 180.0D / Math.PI);
      this.prevRotationPitch =
          this.rotationPitch = (float) (Math.atan2(this.motionY, f) * 180.0D / Math.PI);
    }

    // 激突したブロックを確認している
    Block i = this.worldObj.getBlock(this.xTile, this.yTile, this.zTile);
    boolean air = this.worldObj.isAirBlock(xTile, yTile, zTile);

    // 空気じゃないブロックに当たった&ブロック貫通エンティティでない時
    if (i != null && i.getMaterial() != Material.air) {
      i.setBlockBoundsBasedOnState(this.worldObj, this.xTile, this.yTile, this.zTile);
      AxisAlignedBB axisalignedbb =
          i.getCollisionBoundingBoxFromPool(this.worldObj, this.xTile, this.yTile, this.zTile);

      // 当たり判定に接触しているかどうか
      if (axisalignedbb != null
          && axisalignedbb.isVecInside(Vec3.createVectorHelper(this.posX, this.posY, this.posZ))) {
        this.inGround = true;
      }
    }

    // 空気じゃないブロックに当たった
    if (this.inGround) {
      Block j = this.worldObj.getBlock(this.xTile, this.yTile, this.zTile);
      int k = this.worldObj.getBlockMetadata(this.xTile, this.yTile, this.zTile);

      /*
       * 前のTickに確認した埋まりブロックのIDとメタを照合している。違ったら埋まり状態を解除、一致したら埋まり状態を継続。
       * /* 埋まり状態2tick継続でこのエンティティを消す
       */
      if (j == this.inTile && k == this.inData) {
        ++this.ticksInGround;
        // ブロック貫通の場合、20tick(1秒間)はブロック中にあっても消えないようになる。
        int limit = 2;

        if (this.ticksInGround > limit) {
          explode = true;
        }
      } else // 埋まり状態の解除処理
      {
        this.inGround = false;
        this.motionX *= this.rand.nextFloat() * 0.1F;
        this.motionY *= this.rand.nextFloat() * 0.1F;
        this.motionZ *= this.rand.nextFloat() * 0.1F;
        this.ticksInGround = 0;
        this.ticksInAir = 0;
      }
    } else // 埋まってない時。速度の更新。
    {
      ++this.ticksInAir;
      // ブロックとの衝突判定
      Vec3 vec3 = Vec3.createVectorHelper(this.posX, this.posY, this.posZ);
      Vec3 vec31 =
          Vec3.createVectorHelper(
              this.posX + this.motionX, this.posY + this.motionY, this.posZ + this.motionZ);
      MovingObjectPosition movingobjectposition =
          this.worldObj.func_147447_a(vec3, vec31, false, true, false);
      vec3 = Vec3.createVectorHelper(this.posX, this.posY, this.posZ);
      vec31 =
          Vec3.createVectorHelper(
              this.posX + this.motionX, this.posY + this.motionY, this.posZ + this.motionZ);

      // ブロックに当たった
      if (movingobjectposition != null) {
        vec31 =
            Vec3.createVectorHelper(
                movingobjectposition.hitVec.xCoord,
                movingobjectposition.hitVec.yCoord,
                movingobjectposition.hitVec.zCoord);
      }

      // Entityとの衝突判定。
      List list =
          this.worldObj.getEntitiesWithinAABBExcludingEntity(
              this,
              this.boundingBox
                  .addCoord(this.motionX, this.motionY, this.motionZ)
                  .expand(1.0D, 1.0D, 1.0D));
      double d0 = 0.0D;
      int l;
      float f1;

      MovingObjectPosition entityTarget = null;

      // 1ブロック分の範囲内にいるエンティティ全てに対して繰り返す
      for (l = 0; l < list.size(); ++l) {
        Entity entity1 = (Entity) list.get(l);
        Entity entity = null;

        // ターゲットの場合
        if (entity1 instanceof EntityLivingBase || entity1 instanceof EntityDragonPart) {
          f1 = 0.3F;
          AxisAlignedBB axisalignedbb1 = entity1.boundingBox.expand(f1, f1, f1);
          MovingObjectPosition movingobjectposition1 =
              axisalignedbb1.calculateIntercept(vec3, vec31);

          if (movingobjectposition1 != null) {
            double d1 = vec3.distanceTo(movingobjectposition1.hitVec);

            if (d1 < d0 || d0 == 0.0D) {
              // arrowと異なり、あたったEntityすべてをリストに入れる
              entityTarget = new MovingObjectPosition(entity1);
              d0 = d1;
              break;
            }
          }
        }
      }

      /*
       * 当たったエンティティそれそれについての判定部分。
       * ここで特定の種類のエンティティに当たらないようにできる。
       */
      boolean canAttack = false;
      if (entityTarget != null) {
        Entity target = entityTarget.entityHit;

        if (target instanceof EntityPlayer) {
          // プレイヤーに当たった時
          EntityPlayer entityplayer = (EntityPlayer) target;

          if (entityplayer.capabilities.disableDamage
              || this.shootingEntity instanceof EntityPlayer
                  && !((EntityPlayer) this.shootingEntity).canAttackPlayer(entityplayer)) {
            // PvPが許可されていないと当たらない
            canAttack = false;
          } else if (entityplayer == this.shootingEntity) {
            // 対象が撃った本人の場合も当たらない
            canAttack = false;
          } else if (DCsConfig.PvPProhibitionMode && entityplayer instanceof EntityPlayer) {
            canAttack = false;
          }
        } else if (target instanceof EntityTameable || target instanceof EntityHorse) {
          // 事故防止の為、EntityTameable(犬や猫などのペット)、馬にも当たらないようにする
          canAttack = false;
        } else {
          canAttack = true;
        }
      }

      float f2;
      float f3;

      // 当たったあとの処理
      // まずはリストから
      if (canAttack) {
        Entity target = entityTarget.entityHit;

        int i1 = MathHelper.ceiling_double_int(1.0D * this.damage);
        // 0~2程度の乱数値を上乗せ
        i1 += this.rand.nextInt(3);

        DamageSource damagesource = null;

        // 別メソッドでダメージソースを確認
        damagesource = this.thisDamageSource(this.shootingEntity);

        // バニラ矢と同様、このエンティティが燃えているなら対象に着火することも出来る
        if (this.isBurning() && !(target instanceof EntityEnderman)) {
          target.setFire(5);
        } else if (target instanceof IProjectile) {
          // 対象が矢などの飛翔Entityの場合、打ち消すことが出来る
          target.setDead();
        } else {
          // ダメージを与える処理を呼ぶ
          if (target.attackEntityFrom(damagesource, i1)) {
            // ダメージを与えることに成功したら以下の処理を行う
            if (target instanceof EntityLivingBase) {
              EntityLivingBase entitylivingbase = (EntityLivingBase) target;

              // ノックバック
              if (this.knockbackStrength > 0) {
                f3 =
                    MathHelper.sqrt_double(
                        this.motionX * this.motionX + this.motionZ * this.motionZ);

                if (f3 > 0.0F) {
                  // Y方向に大きめに打ち上げる
                  target.addVelocity(
                      this.motionX * this.knockbackStrength * 0.2000000238418579D / f3,
                      0.3D,
                      this.motionZ * this.knockbackStrength * 0.2000000238418579D / f3);
                }
              }

              // 無敵時間はなし
              target.hurtResistantTime = 0;

              // マルチプレイ時に、両者がプレイヤーだった時のパケット送信処理
              if (this.shootingEntity != null
                  && target != this.shootingEntity
                  && target instanceof EntityPlayer
                  && this.shootingEntity instanceof EntityPlayerMP) {
                ((EntityPlayerMP) this.shootingEntity)
                    .playerNetServerHandler.sendPacket(new S2BPacketChangeGameState(6, 0.0F));
              }
            }

            // ここでヒット時の効果音がなる
            this.playSound("random.bowhit", 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F));

            // 当たったあと、弾を消去する。エンティティ貫通がONの弾種はそのまま残す。
            explode = true;
          }
        }
      }

      if (movingobjectposition != null) // blockのみ
      {
        this.xTile = movingobjectposition.blockX;
        this.yTile = movingobjectposition.blockY;
        this.zTile = movingobjectposition.blockZ;
        this.inTile = this.worldObj.getBlock(this.xTile, this.yTile, this.zTile);
        this.inData = this.worldObj.getBlockMetadata(this.xTile, this.yTile, this.zTile);
        this.motionX = ((float) (movingobjectposition.hitVec.xCoord - this.posX));
        this.motionY = ((float) (movingobjectposition.hitVec.yCoord - this.posY));
        this.motionZ = ((float) (movingobjectposition.hitVec.zCoord - this.posZ));
        f2 =
            MathHelper.sqrt_double(
                this.motionX * this.motionX
                    + this.motionY * this.motionY
                    + this.motionZ * this.motionZ);
        this.posX -= this.motionX / f2 * 0.05000000074505806D;
        this.posY -= this.motionY / f2 * 0.05000000074505806D;
        this.posZ -= this.motionZ / f2 * 0.05000000074505806D;
        this.playSound("random.bowhit", 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F));
        this.inGround = true;

        if (this.inTile != null) {
          // Block側に衝突を伝える
          this.inTile.onEntityCollidedWithBlock(
              this.worldObj, this.xTile, this.yTile, this.zTile, this);
        }
      }
    }

    // さいごに爆発処理
    int live = (targetEntity != null && targetEntity.isEntityAlive()) ? 10 : 600;

    if (explode || this.livingTimeCount > live) {
      if (this.isExploded() == 0) {
        AMTLogger.debugInfo("explosion");
        this.setExplosion();
        if (!DCsConfig.disableMissileExplosion && !worldObj.isRemote) {
          float f = 5.0F;
          CustomExplosion explosion =
              new CustomExplosion(
                  worldObj,
                  this,
                  shootingEntity,
                  this.posX,
                  this.posY,
                  this.posZ,
                  f,
                  CustomExplosion.Type.Anchor,
                  true);
          explosion.doExplosion();
        }
      }
    }

    // 追尾
    if (active) {
      if (targetEntity != null && targetEntity.isEntityAlive()) {
        double dx = targetEntity.posX - this.posX;
        double dy = targetEntity.boundingBox.minY + (targetEntity.height / 2.0D) - this.posY;
        double dz = targetEntity.posZ - this.posZ;
        double d3 = MathHelper.sqrt_double(dx * dx + dz * dz);

        if (d3 >= 1.0E-7D) {
          float f4 = (float) d3 * 0.2F;
          double dy2 = dy + f4;

          float ff = MathHelper.sqrt_double(dx * dx + dy2 * dy2 + dz * dz);
          dx /= ff;
          dy /= ff;
          dz /= ff;

          this.motionX = (this.motionX + dx) / 2;
          this.motionY = (this.motionY + dy) / 2;
          this.motionZ = (this.motionZ + dz) / 2;

          this.motionX *= 1.25D;
          this.motionY *= 1.25D;
          this.motionZ *= 1.25D;
        }
      }
    }

    // 直前のパラメータと新パラメータを一致させているところ。
    // また、速度に応じてエンティティの向きを調整し、常に進行方向に前面が向くようにしている。
    if (this.prevRotationPitch == 0.0F && this.prevRotationYaw == 0.0F) {
      float f = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ);
      this.prevRotationYaw =
          this.rotationYaw = (float) (Math.atan2(this.motionX, this.motionZ) * 180.0D / Math.PI);
      this.prevRotationPitch =
          this.rotationPitch = (float) (Math.atan2(this.motionY, f) * 180.0D / Math.PI);
    }

    // 改めてポジションに速度を加算。向きも更新。
    this.posX += this.motionX;
    this.posY += this.motionY;
    this.posZ += this.motionZ;
    float f2 = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ);
    this.rotationYaw = (float) (Math.atan2(this.motionX, this.motionZ) * 180.0D / Math.PI);
    this.rotationPitch = (float) (Math.atan2(this.motionY, f2) * 180.0D / Math.PI);

    while (this.rotationPitch - this.prevRotationPitch < -180.0F) {
      this.prevRotationPitch -= 360.0F;
    }

    while (this.rotationPitch - this.prevRotationPitch >= 180.0F) {
      this.prevRotationPitch += 360.0F;
    }

    while (this.rotationYaw - this.prevRotationYaw < -180.0F) {
      this.prevRotationYaw -= 360.0F;
    }

    while (this.rotationYaw - this.prevRotationYaw >= 180.0F) {
      this.prevRotationYaw += 360.0F;
    }

    this.rotationPitch =
        this.prevRotationPitch + (this.rotationPitch - this.prevRotationPitch) * 0.2F;
    this.rotationYaw = this.prevRotationYaw + (this.rotationYaw - this.prevRotationYaw) * 0.2F;

    // 水中に有る
    if (this.isInWater()) {
      // 泡パーティクルが出る
      for (int j1 = 0; j1 < 4; ++j1) {
        float f3 = 0.25F;
        this.worldObj.spawnParticle(
            "bubble",
            this.posX - this.motionX * f3,
            this.posY - this.motionY * f3,
            this.posZ - this.motionZ * f3,
            this.motionX,
            this.motionY,
            this.motionZ);
      }
    }

    this.setPosition(this.posX, this.posY, this.posZ);
    this.func_145775_I();
  }
Ejemplo n.º 4
0
 @Override
 protected void onImpact(MovingObjectPosition mop) {
   if (mop.typeOfHit == MovingObjectType.BLOCK) {
     Block block = worldObj.getBlock(mop.blockX, mop.blockY, mop.blockZ);
     if (!isInGround() && ticksExisted < getMaxDistance()) {
       WorldUtils.playSoundAtEntity(this, Sounds.WHIP_CRACK, 1.0F, 0.2F);
       motionX = motionY = motionZ = 0.0D;
       if (canGrabBlock(block, mop.blockX, mop.blockY, mop.blockZ, mop.sideHit)) {
         setInGround(true);
         AxisAlignedBB box =
             block.getCollisionBoundingBoxFromPool(worldObj, mop.blockX, mop.blockY, mop.blockZ);
         // bounding box may be null, depending on the block
         if (box != null) {
           posX = box.minX + ((box.maxX - box.minX) / 2.0D);
           posY = box.minY + ((box.maxY - box.minY) / 2.0D);
           posZ = box.minZ + ((box.maxZ - box.minZ) / 2.0D);
           switch (mop.sideHit) {
             case 5:
               posX = box.maxX;
               break; // EAST
             case 4:
               posX = box.minX - 0.015D;
               break; // WEST (a little extra to compensate for block border, otherwise renders
                      // black)
             case 3:
               posZ = box.maxZ;
               break; // SOUTH
             case 2:
               posZ = box.minZ - 0.015D;
               break; // NORTH (a little extra to compensate for block border, otherwise renders
                      // black)
             case SideHit.TOP:
               posY = box.maxY;
               break;
             case SideHit.BOTTOM:
               posY = box.minY - 0.015D;
               break;
           }
         } else {
           // adjusting posX/Y/Z here seems to make no difference to the rendering, even when
           // client side makes same changes
           posX = (double) mop.blockX + 0.5D;
           posY = (double) mop.blockY + 0.5D;
           posZ = (double) mop.blockZ + 0.5D;
           // side hit documentation is wrong!!! based on printing out mop.sideHit:
           // 2 = NORTH (face of block), 3 = SOUTH, 4 = WEST, 5 = EAST, 0 = BOTTOM, 1 = TOP
           switch (mop.sideHit) {
               // case 5: posX += 0.5D; break; // EAST
               // case 4: posX -= 0.515D; break; // WEST (a little extra to compensate for block
               // border, otherwise renders black)
               // case 3: posZ += 0.5D; break; // SOUTH
               // case 2: posZ -= 0.515D; break; // NORTH (a little extra to compensate for block
               // border, otherwise renders black)
             case SideHit.TOP:
               posY = mop.blockY + 1.0D;
               break;
             case SideHit.BOTTOM:
               posY = mop.blockY - 0.015D;
               break;
           }
         }
         // however, setting position as watched values and using these on the client works...
         // weird
         dataWatcher.updateObject(HIT_POS_X, (float) posX);
         dataWatcher.updateObject(HIT_POS_Y, (float) posY);
         dataWatcher.updateObject(HIT_POS_Z, (float) posZ);
         // unfortunately, this means the datawatcher values are no longer usable for getting the
         // block,
         // so need to store hitX/Y/Z separately for updating
         hitX = mop.blockX;
         hitY = mop.blockY;
         hitZ = mop.blockZ;
       } else if (canBreakBlock(
           block, block.getMaterial(), mop.blockX, mop.blockY, mop.blockZ, mop.sideHit)) {
         if (!worldObj.isRemote) {
           // don't drop items for players in creative mode
           boolean drop =
               (getThrower() instanceof EntityPlayer
                   ? !(((EntityPlayer) getThrower()).capabilities.isCreativeMode)
                   : true);
           worldObj.func_147480_a(mop.blockX, mop.blockY, mop.blockZ, drop);
           setDead();
         }
       } else if (block.getMaterial().blocksMovement()) {
         // Only call onEntityCollidedWithBlock if the whip didn't already grab or break the block
         block.onEntityCollidedWithBlock(worldObj, mop.blockX, mop.blockY, mop.blockZ, this);
       } else {
         block.onEntityCollidedWithBlock(worldObj, mop.blockX, mop.blockY, mop.blockZ, this);
         return;
       }
     }
   } else if (mop.entityHit != null) {
     worldObj.playSoundAtEntity(mop.entityHit, Sounds.WHIP_CRACK, 1.0F, 1.0F);
     boolean inflictDamage = true; // set to false if held item disarmed
     if (mop.entityHit instanceof EntityLivingBase) {
       EntityLivingBase target = (EntityLivingBase) mop.entityHit;
       if (getThrower() instanceof EntityPlayer) {
         EntityPlayer player = (EntityPlayer) getThrower();
         if (lootTarget(player, target)) {
           inflictDamage =
               (target instanceof IEntityLootable
                   ? ((IEntityLootable) target).isHurtOnTheft(player, getType())
                   : Config.getHurtOnSteal());
         } else if (target.getHeldItem() != null
             && ZSSPlayerSkills.get(player).hasSkill(SkillBase.parry)) {
           float chance = Parry.getDisarmModifier(player, target);
           float yaw = (target.rotationYaw - player.rotationYaw);
           while (yaw >= 360.0F) {
             yaw -= 360.0F;
           }
           while (yaw < 0.0F) {
             yaw += 360.0F;
           }
           yaw = Math.abs(Math.abs(yaw) - 180.0F);
           // should be impossible to disarm from more than 90 degrees to either side
           // however, rotationYaw does not seem to be the most reliable, but it's close enough
           float mod = 0.5F - (0.25F * (yaw / 45.0F));
           chance = 0.05F + (chance * mod); // max chance is 0.3F, min is 0.05F
           if (worldObj.rand.nextFloat() < chance) {
             WorldUtils.dropHeldItem(target);
             inflictDamage = false;
           }
         }
       }
       if (inflictDamage && target.getEquipmentInSlot(ArmorIndex.EQUIPPED_CHEST) != null) {
         inflictDamage = false; // cannot damage armor-wearing opponents
       }
     }
     if (inflictDamage) {
       mop.entityHit.attackEntityFrom(getDamageSource(), getDamage());
     }
     setDead();
   }
 }
Ejemplo n.º 5
0
  @Override
  public void onUpdate() {
    super.onEntityUpdate();

    if (prevRotationPitch == 0.0F && prevRotationYaw == 0.0F) {
      float f = MathHelper.sqrt_double(motionX * motionX + motionZ * motionZ);
      prevRotationYaw = rotationYaw = (float) (Math.atan2(motionX, motionZ) * 180.0D / Math.PI);
      prevRotationPitch = rotationPitch = (float) (Math.atan2(motionY, f) * 180.0D / Math.PI);
    }

    // TODO: worldObj.getBlock()
    Block block = worldObj.getBlock(xTile, yTile, zTile);

    // TODO: block.getMaterial()  Material.air
    if (block.getMaterial() != Material.air) {
      // TODO: setBlockBoundsBasedOnState
      block.setBlockBoundsBasedOnState(worldObj, xTile, yTile, zTile);
      // TODO:						        getCollisionBoundingBoxFromPool()
      AxisAlignedBB axisalignedbb =
          block.getCollisionBoundingBoxFromPool(worldObj, xTile, yTile, zTile);

      if (axisalignedbb != null
          && axisalignedbb.isVecInside(
              worldObj.getWorldVec3Pool().getVecFromPool(posX, posY, posZ))) {
        this.setDead();
      }
    }

    ++ticksInAir;
    Vec3 vec3 = worldObj.getWorldVec3Pool().getVecFromPool(posX, posY, posZ);
    Vec3 vec31 =
        worldObj.getWorldVec3Pool().getVecFromPool(posX + motionX, posY + motionY, posZ + motionZ);
    // TODO: 											 rayTraceBlocks_do_do()?
    MovingObjectPosition movingobjectposition =
        worldObj.func_147447_a(vec3, vec31, false, true, false);
    vec3 = worldObj.getWorldVec3Pool().getVecFromPool(posX, posY, posZ);
    vec31 =
        worldObj.getWorldVec3Pool().getVecFromPool(posX + motionX, posY + motionY, posZ + motionZ);

    if (movingobjectposition != null) {
      vec31 =
          worldObj
              .getWorldVec3Pool()
              .getVecFromPool(
                  movingobjectposition.hitVec.xCoord,
                  movingobjectposition.hitVec.yCoord,
                  movingobjectposition.hitVec.zCoord);
    }

    Entity entity = null;
    List list =
        worldObj.getEntitiesWithinAABBExcludingEntity(
            this, boundingBox.addCoord(motionX, motionY, motionZ).expand(1.0D, 1.0D, 1.0D));
    double d0 = 0.0D;
    int l;
    float f1;

    for (l = 0; l < list.size(); ++l) {
      Entity entity1 = (Entity) list.get(l);

      if (entity1.canBeCollidedWith() && (entity1 != shootingEntity || ticksInAir >= 5)) {
        f1 = 0.3F;
        AxisAlignedBB axisalignedbb1 = entity1.boundingBox.expand(f1, f1, f1);
        MovingObjectPosition movingobjectposition1 = axisalignedbb1.calculateIntercept(vec3, vec31);

        if (movingobjectposition1 != null) {
          double d1 = vec3.distanceTo(movingobjectposition1.hitVec);

          if (d1 < d0 || d0 == 0.0D) {
            entity = entity1;
            d0 = d1;
          }
        }
      }
    }

    if (entity != null) {
      movingobjectposition = new MovingObjectPosition(entity);
    }

    if (movingobjectposition != null
        && movingobjectposition.entityHit != null
        && movingobjectposition.entityHit instanceof EntityPlayer) {
      EntityPlayer entityplayer = (EntityPlayer) movingobjectposition.entityHit;

      if (entityplayer.capabilities.disableDamage
          || shootingEntity instanceof EntityPlayer
              && !((EntityPlayer) shootingEntity).canAttackPlayer(entityplayer)) {
        movingobjectposition = null;
      }
    }

    float f2;
    float f3;

    if (movingobjectposition != null) {
      if (movingobjectposition.entityHit != null) {
        f2 = MathHelper.sqrt_double(motionX * motionX + motionY * motionY + motionZ * motionZ);

        DamageSource damagesource = null;

        if (shootingEntity == null) {
          damagesource = DamageSource.causeArrowDamage(this, this);
        } else {
          damagesource = DamageSource.causeArrowDamage(this, shootingEntity);
        }

        if (type == DartType.POISON) {
          damage = 1;

          if (movingobjectposition.entityHit instanceof EntityLivingBase) {
            ((EntityLivingBase) movingobjectposition.entityHit)
                .addPotionEffect(new PotionEffect(BOPPotionHelper.get("paralysis").id, 100));
          }
        }

        if (movingobjectposition.entityHit.attackEntityFrom(damagesource, damage)) {
          if (movingobjectposition.entityHit instanceof EntityLivingBase) {
            if (shootingEntity != null
                && movingobjectposition.entityHit != shootingEntity
                && movingobjectposition.entityHit instanceof EntityPlayer
                && shootingEntity instanceof EntityPlayerMP) {
              // TODO:													sendPacketToPlayer()
              ((EntityPlayerMP) shootingEntity)
                  .playerNetServerHandler.sendPacket(new S2BPacketChangeGameState(6, 0.0F));
            }
          }

          this.playSound("random.bowhit", 1.0F, 1.2F / (rand.nextFloat() * 0.2F + 0.9F));
          this.setDead();
        } else {
          motionX *= -0.10000000149011612D;
          motionY *= -0.10000000149011612D;
          motionZ *= -0.10000000149011612D;
          rotationYaw += 180.0F;
          prevRotationYaw += 180.0F;
          ticksInAir = 0;
        }
      } else {
        xTile = movingobjectposition.blockX;
        yTile = movingobjectposition.blockY;
        zTile = movingobjectposition.blockZ;
        motionX = ((float) (movingobjectposition.hitVec.xCoord - posX));
        motionY = ((float) (movingobjectposition.hitVec.yCoord - posY));
        motionZ = ((float) (movingobjectposition.hitVec.zCoord - posZ));
        f2 = MathHelper.sqrt_double(motionX * motionX + motionY * motionY + motionZ * motionZ);
        posX -= motionX / f2 * 0.05000000074505806D;
        posY -= motionY / f2 * 0.05000000074505806D;
        posZ -= motionZ / f2 * 0.05000000074505806D;

        for (int p = 0; p < 16; ++p) {
          if (isPoisonous()) {
            BiomesOPlenty.proxy.spawnParticle("poisondart", posX, posY, posZ);
          } else {
            BiomesOPlenty.proxy.spawnParticle("dart", posX, posY, posZ);
          }
        }

        this.playSound("random.bowhit", 1.0F, 1.2F / (rand.nextFloat() * 0.2F + 0.9F));
        this.setDead();
      }
    }

    posX += motionX;
    posY += motionY;
    posZ += motionZ;
    f2 = MathHelper.sqrt_double(motionX * motionX + motionZ * motionZ);
    rotationYaw = (float) (Math.atan2(motionX, motionZ) * 180.0D / Math.PI);

    for (rotationPitch = (float) (Math.atan2(motionY, f2) * 180.0D / Math.PI);
        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 f4 = 0.99F;
    f1 = 0.05F;

    if (this.isInWater()) {
      for (int j1 = 0; j1 < 4; ++j1) {
        f3 = 0.25F;
        worldObj.spawnParticle(
            "bubble",
            posX - motionX * f3,
            posY - motionY * f3,
            posZ - motionZ * f3,
            motionX,
            motionY,
            motionZ);
      }

      f4 = 0.8F;
    }

    motionX *= f4;
    motionY *= f4;
    motionZ *= f4;
    motionY -= f1;
    this.setPosition(posX, posY, posZ);
    // TODO: doBlockCollisions()
    this.func_145775_I();
  }