Program: 34711
Project: 34711
Buggy source:
@Override public void onLivingUpdate(){
  if (noPlayers) {
    if (ticksExisted % 10 == 0 && !attacks.getViablePlayers().isEmpty())     noPlayers=false;
 else     return;
  }
 else   if (ticksExisted % 40 == 0 && attacks.getViablePlayers().isEmpty()) {
    noPlayers=true;
    return;
  }
  if (currentAttack == null)   currentAttack=defaultAttack;
  angryStatus=isAngry();
  if (!worldObj.isRemote) {
    if (spawnCooldown > 0 && --spawnCooldown > 0 && ticksExisted % 20 == 0) {
      for (      EntityPlayer player : attacks.getViablePlayers()) {
        if (worldObj.getBlock(MathUtil.floor(player.posX),MathUtil.floor(player.posY) - 1,MathUtil.floor(player.posZ)) == Blocks.end_stone) {
          spawnCooldown=0;
          break;
        }
      }
    }
    if (loadTimer > 0 && --loadTimer == 1) {
      for (int chunkX=-6; chunkX <= 6; chunkX++) {
        for (int chunkZ=-6; chunkZ <= 6; chunkZ++)         worldObj.getChunkFromChunkCoords(chunkX,chunkZ);
      }
    }
    if (loadTimer == 0 && !angryStatus && ticksExisted % 10 == 0) {
      DragonSavefile save=WorldDataHandler.get(DragonSavefile.class);
      if (save.countCrystals() <= 2 + save.getDragonDeathAmount() || attacks.getHealthPercentage() <= 80) {
        setAngry(true);
        spawnCooldown=0;
      }
    }
    currentAttack.update();
    if (angryStatus) {
      DebugBoard.updateValue("String_Node_Str",currentAttack.id);
      if (currentAttack.equals(defaultAttack)) {
        if (nextAttackTicks-- <= 0 && target == null) {
          lastAttack=currentAttack;
          if ((currentAttack=attacks.pickSpecialAttack(lastAttack)) == null)           nextAttackTicks=(currentAttack=defaultAttack).getNextAttackTimer();
          currentAttack.init();
        }
      }
 else       if (currentAttack.hasEnded() || forceAttackEnd) {
        forceAttackEnd=false;
        currentAttack.end();
        nextAttackTicks=MathUtil.ceil(currentAttack.getNextAttackTimer() * (0.5D + attacks.getHealthPercentage() / 200D));
        (currentAttack=defaultAttack).init();
      }
    }
    if (getHealth() > 0) {
      rewards.updateManager();
      achievements.updateManager();
      if (dragonHurtTime > 0)       --dragonHurtTime;
      double spd=currentAttack.overrideMovementSpeed();
      if (moveSpeedMp > spd)       moveSpeedMp=moveSpeedMp < 0.2D && spd == 0D ? 0D : Math.max(spd,moveSpeedMp - 0.0175D);
 else       if (moveSpeedMp < spd)       moveSpeedMp=Math.min(spd,moveSpeedMp + 0.0175D);
      float wng=frozen ? HeeDebugCommand.overrideWingSpeed : currentAttack.overrideWingSpeed(), curWng=getWingSpeed();
      if (curWng > wng)       curWng=Math.max(wng,curWng - 0.015F);
 else       if (curWng < wng)       curWng=Math.min(wng,curWng + 0.015F);
      if (curWng != getWingSpeed())       setWingSpeed(curWng);
      if (ticksExisted % 2 == 0) {
        int perc=attacks.getHealthPercentage();
        if (perc < 40 && rand.nextInt(500 - (50 - perc) * 8) == 0) {
          int x=(int)posX + rand.nextInt(301) - 150, z=(int)posZ + rand.nextInt(301) - 150;
          int y=1 + DragonUtil.getTopBlockY(worldObj,Blocks.end_stone,x,z);
          EntityMobAngryEnderman buddy=new EntityMobAngryEnderman(worldObj);
          buddy.setPosition(x,y,z);
          worldObj.addWeatherEffect(new EntityWeatherLightningBoltSafe(worldObj,x,y,z));
          worldObj.spawnEntityInWorld(buddy);
        }
        lastUpdate=worldObj.getTotalWorldTime();
      }
    }
    if (Log.isDebugEnabled())     DragonDebugManager.updateBoard(this);
  }
  if (worldObj.isRemote && MathHelper.cos(prevAnimTime * (float)Math.PI * 2F) <= -0.3F && MathHelper.cos(animTime * (float)Math.PI * 2F) >= -0.3F) {
    worldObj.playSound(posX,posY,posZ,"String_Node_Str",5F,0.8F + rand.nextFloat() * 0.3F,false);
  }
  prevAnimTime=animTime;
  if (getHealth() <= 0F)   worldObj.spawnParticle("String_Node_Str",posX + (rand.nextFloat() - 0.5F) * 8F,posY + 2D + (rand.nextFloat() - 0.5F) * 4F,posZ + (rand.nextFloat() - 0.5F) * 8F,0D,0D,0D);
 else {
    updateEnderCrystal();
    float animAdvance=0.2F / (MathHelper.sqrt_double(motionX * motionX + motionZ * motionZ) * 10F + 1F);
    animAdvance*=(float)Math.pow(2D,motionY);
    animAdvance*=getWingSpeed();
    animTime+=slowed ? animAdvance * 0.5F : animAdvance;
    rotationYaw=MathHelper.wrapAngleTo180_float(rotationYaw);
    if (movementBufferIndex < 0) {
      for (int index=0; index < movementBuffer.length; ++index) {
        movementBuffer[index][0]=rotationYaw;
        movementBuffer[index][1]=posY;
      }
    }
    if (++movementBufferIndex == movementBuffer.length)     movementBufferIndex=0;
    movementBuffer[movementBufferIndex][0]=rotationYaw;
    movementBuffer[movementBufferIndex][1]=posY;
    if (worldObj.isRemote) {
      if (newPosRotationIncrements > 0) {
        double finalPosX=posX + (newPosX - posX) / newPosRotationIncrements, finalPosY=posY + (newPosY - posY) / newPosRotationIncrements, finalPosZ=posZ + (newPosZ - posZ) / newPosRotationIncrements;
        rotationYaw=(float)(rotationYaw + MathHelper.wrapAngleTo180_double(newRotationYaw - rotationYaw) / newPosRotationIncrements);
        rotationPitch=(float)(rotationPitch + (newRotationPitch - rotationPitch) / newPosRotationIncrements);
        --newPosRotationIncrements;
        setPosition(finalPosX,finalPosY,finalPosZ);
        setRotation(rotationYaw,rotationPitch);
      }
    }
 else {
      double xDiff=targetX - posX, yDiff=targetY - posY, zDiff=targetZ - posZ;
      double distFromTargetSq=xDiff * xDiff + yDiff * yDiff + zDiff * zDiff;
      if (target != null) {
        targetX=target.posX;
        targetZ=target.posZ;
        targetY=target.boundingBox.minY + Math.min(0.4D + Math.sqrt(Math.pow(targetX - posX,2) + Math.pow(targetZ - posZ,2)) / 80D - 1D,10D);
      }
 else       trySetTargetPosition(targetX + rand.nextGaussian() * 2D,targetY,targetZ + rand.nextGaussian() * 2D);
      if ((target != null && target.isDead) || distFromTargetSq > 22500D)       forceAttackEnd=forceNewTarget=true;
      if (forceNewTarget || distFromTargetSq < 64D || distFromTargetSq > 22500D || isCollidedHorizontally || isCollidedVertically) {
        setNewTarget();
      }
      yDiff=MathUtil.clamp(yDiff / MathUtil.distance(xDiff,zDiff),-0.6F,0.6F);
      motionY+=yDiff * 0.1D;
      rotationYaw=MathHelper.wrapAngleTo180_float(rotationYaw);
      double d9=MathUtil.clamp(MathHelper.wrapAngleTo180_double(180D - MathUtil.toDeg(Math.atan2(xDiff,zDiff)) - rotationYaw),-50D,50D);
      Vec3 targetDiffVec=Vec3.createVectorHelper(targetX - posX,targetY - posY,targetZ - posZ).normalize();
      Vec3 rotationVec=Vec3.createVectorHelper(MathHelper.sin(MathUtil.toRad(rotationYaw)),motionY,(-MathHelper.cos(MathUtil.toRad(rotationYaw)))).normalize();
      float f4=Math.max((float)(rotationVec.dotProduct(targetDiffVec) + 0.5D) / 1.5F,0F);
      randomYawVelocity*=0.8F;
      float speed=MathHelper.sqrt_double(motionX * motionX + motionZ * motionZ) + 1F;
      double speedLimited=Math.min(Math.sqrt(motionX * motionX + motionZ * motionZ) + 1D,40D);
      randomYawVelocity=(float)(randomYawVelocity + d9 * (0.7D / speedLimited / speed));
      rotationYaw+=randomYawVelocity * 0.1F;
      float f6=(float)(2D / (speedLimited + 1D));
      moveFlying(0F,-1F,0.06F * (f4 * f6 + (1F - f6)));
      if (frozen)       motionX=motionY=motionZ=0D;
      MotionUpdateEvent event=new MotionUpdateEvent(motionX,motionY,motionZ);
      currentAttack.onMotionUpdateEvent(event);
      motionX=event.motionX;
      motionY=event.motionY;
      motionZ=event.motionZ;
      if (slowed)       moveEntity(motionX * moveSpeedMp * 0.8D,motionY * moveSpeedMp * 0.8D,motionZ * moveSpeedMp * 0.8D);
 else       moveEntity(motionX * moveSpeedMp,motionY * moveSpeedMp,motionZ * moveSpeedMp);
      double motionMultiplier=0.8D + 0.15D * ((Vec3.createVectorHelper(motionX,motionY,motionZ).normalize().dotProduct(rotationVec) + 1D) * 0.5D);
      motionX*=motionMultiplier;
      motionZ*=motionMultiplier;
      motionY*=0.91D;
    }
    renderYawOffset=rotationYaw;
    dragonPartHead.width=dragonPartHead.height=3F;
    dragonPartTail1.width=dragonPartTail1.height=2F;
    dragonPartTail2.width=dragonPartTail2.height=2F;
    dragonPartTail3.width=dragonPartTail3.height=2F;
    dragonPartBody.width=5F;
    dragonPartBody.height=3F;
    dragonPartWing1.width=4F;
    dragonPartWing1.height=2F;
    dragonPartWing2.width=4F;
    dragonPartWing2.height=3F;
    float offsetAngle=MathUtil.toRad((float)(getMovementOffsets(5,1F)[1] - getMovementOffsets(10,1F)[1]) * 10F);
    float angleCos=MathHelper.cos(offsetAngle);
    float angleSin=-MathHelper.sin(offsetAngle);
    float yawRad=MathUtil.toRad(rotationYaw);
    float yawSin=MathHelper.sin(yawRad);
    float yawCos=MathHelper.cos(yawRad);
    dragonPartBody.onUpdate();
    dragonPartBody.setLocationAndAngles(posX + yawSin * 0.5F,posY,posZ - yawCos * 0.5F,0F,0F);
    dragonPartWing1.onUpdate();
    dragonPartWing1.setLocationAndAngles(posX + yawCos * 4.5F,posY + 2D,posZ + yawSin * 4.5F,0F,0F);
    dragonPartWing2.onUpdate();
    dragonPartWing2.setLocationAndAngles(posX - yawCos * 4.5F,posY + 2D,posZ - yawSin * 4.5F,0F,0F);
    collideWithEntities(worldObj.getEntitiesWithinAABBExcludingEntity(this,dragonPartWing1.boundingBox.expand(3.5D,2D,3.5D).offset(0D,-2D,0D)));
    collideWithEntities(worldObj.getEntitiesWithinAABBExcludingEntity(this,dragonPartWing2.boundingBox.expand(3.5D,2D,3.5D).offset(0D,-2D,0D)));
    collideWithEntities(worldObj.getEntitiesWithinAABBExcludingEntity(this,dragonPartHead.boundingBox.expand(0.7D,1D,0.7D)));
    double[] oldOffsets=getMovementOffsets(5,1F), currentOffsets=getMovementOffsets(0,1F);
    float moveX=MathHelper.sin(MathUtil.toRad(rotationYaw) - randomYawVelocity * 0.01F);
    float moveZ=MathHelper.cos(MathUtil.toRad(rotationYaw) - randomYawVelocity * 0.01F);
    dragonPartHead.onUpdate();
    dragonPartHead.setLocationAndAngles(posX + moveX * 5.5F * angleCos,posY + currentOffsets[1] - oldOffsets[1] + angleSin * 5.5F,posZ - moveZ * 5.5F * angleCos,0F,0F);
    for (int part=0; part < 3; part++) {
      EntityDragonPart tailPart=part == 0 ? dragonPartTail1 : part == 1 ? dragonPartTail2 : dragonPartTail3;
      double[] partOffsets=getMovementOffsets(12 + part * 2,1F);
      float partYaw=MathUtil.toRad(rotationYaw) + MathUtil.toRad((float)MathHelper.wrapAngleTo180_double(partOffsets[0] - oldOffsets[0]));
      float partYawSin=MathHelper.sin(partYaw);
      float partYawCos=MathHelper.cos(partYaw);
      float partMp=(part + 1) * 2F;
      tailPart.onUpdate();
      tailPart.setLocationAndAngles(posX - ((yawSin * 1.5F + partYawSin * partMp) * angleCos),posY + (partOffsets[1] - oldOffsets[1]) - ((partMp + 1.5F) * angleSin) + 1.5D,posZ + ((yawCos * 1.5F + partYawCos * partMp) * angleCos),0F,0F);
    }
    if (!worldObj.isRemote) {
      slowed=destroyBlocksInAABB(dragonPartHead.boundingBox) | destroyBlocksInAABB(dragonPartBody.boundingBox);
      attacks.updatePassiveAttacks(currentAttack);
      if (currentAttack.id == 10) {
        slowed|=destroyBlocksInAABB(dragonPartWing1.boundingBox) | destroyBlocksInAABB(dragonPartWing2.boundingBox) | destroyBlocksInAABB(dragonPartBody.boundingBox.expand(1D,1D,1D));
      }
    }
  }
}

Fixed version (ground truth):
@Override public void onLivingUpdate(){
  if (noPlayers) {
    if (ticksExisted % 10 == 0 && !attacks.getViablePlayers().isEmpty())     noPlayers=false;
 else     return;
  }
 else   if (ticksExisted % 40 == 0 && attacks.getViablePlayers().isEmpty()) {
    noPlayers=true;
    return;
  }
  if (currentAttack == null)   currentAttack=defaultAttack;
  angryStatus=isAngry();
  if (!worldObj.isRemote) {
    if (spawnCooldown > 0 && --spawnCooldown > 0 && ticksExisted % 20 == 0) {
      for (      EntityPlayer player : attacks.getViablePlayers()) {
        if (worldObj.getBlock(MathUtil.floor(player.posX),MathUtil.floor(player.posY) - 1,MathUtil.floor(player.posZ)) == Blocks.end_stone) {
          spawnCooldown=0;
          break;
        }
      }
    }
    if (loadTimer > 0 && --loadTimer == 1) {
      for (int chunkX=-6; chunkX <= 6; chunkX++) {
        for (int chunkZ=-6; chunkZ <= 6; chunkZ++)         worldObj.getChunkFromChunkCoords(chunkX,chunkZ);
      }
    }
    if (loadTimer == 0 && !angryStatus && ticksExisted % 10 == 0) {
      DragonSavefile save=WorldDataHandler.get(DragonSavefile.class);
      if (save.countCrystals() <= 2 + save.getDragonDeathAmount() || attacks.getHealthPercentage() <= 80) {
        setAngry(true);
        spawnCooldown=0;
      }
    }
    currentAttack.update();
    if (angryStatus) {
      DebugBoard.updateValue("String_Node_Str",currentAttack.id);
      if (currentAttack.equals(defaultAttack)) {
        if (nextAttackTicks-- <= 0 && target == null) {
          lastAttack=currentAttack;
          if ((currentAttack=attacks.pickSpecialAttack(lastAttack)) == null)           nextAttackTicks=(currentAttack=defaultAttack).getNextAttackTimer();
          currentAttack.init();
        }
      }
 else       if (currentAttack.hasEnded() || forceAttackEnd) {
        forceAttackEnd=false;
        currentAttack.end();
        nextAttackTicks=MathUtil.ceil(currentAttack.getNextAttackTimer() * (0.5D + attacks.getHealthPercentage() / 200D));
        (currentAttack=defaultAttack).init();
      }
    }
    if (getHealth() > 0) {
      rewards.updateManager();
      achievements.updateManager();
      if (dragonHurtTime > 0)       --dragonHurtTime;
      double spd=currentAttack.overrideMovementSpeed();
      if (moveSpeedMp > spd)       moveSpeedMp=moveSpeedMp < 0.2D && spd == 0D ? 0D : Math.max(spd,moveSpeedMp - 0.0175D);
 else       if (moveSpeedMp < spd)       moveSpeedMp=Math.min(spd,moveSpeedMp + 0.0175D);
      float wng=frozen ? HeeDebugCommand.overrideWingSpeed : currentAttack.overrideWingSpeed(), curWng=getWingSpeed();
      if (curWng > wng)       curWng=Math.max(wng,curWng - 0.015F);
 else       if (curWng < wng)       curWng=Math.min(wng,curWng + 0.015F);
      if (curWng != getWingSpeed())       setWingSpeed(curWng);
      if (ticksExisted % 2 == 0) {
        int perc=attacks.getHealthPercentage();
        if (perc < 40 && rand.nextInt(500 - (50 - perc) * 8) == 0) {
          int x=(int)posX + rand.nextInt(301) - 150, z=(int)posZ + rand.nextInt(301) - 150;
          int y=1 + DragonUtil.getTopBlockY(worldObj,Blocks.end_stone,x,z);
          EntityMobAngryEnderman buddy=new EntityMobAngryEnderman(worldObj);
          buddy.setPosition(x,y,z);
          worldObj.addWeatherEffect(new EntityWeatherLightningBoltSafe(worldObj,x,y,z));
          worldObj.spawnEntityInWorld(buddy);
        }
        lastUpdate=worldObj.getTotalWorldTime();
      }
    }
    if (Log.isDebugEnabled())     DragonDebugManager.updateBoard(this);
  }
  if (worldObj.isRemote && MathHelper.cos(prevAnimTime * (float)Math.PI * 2F) <= -0.3F && MathHelper.cos(animTime * (float)Math.PI * 2F) >= -0.3F) {
    worldObj.playSound(posX,posY,posZ,"String_Node_Str",5F,0.8F + rand.nextFloat() * 0.3F,false);
  }
  prevAnimTime=animTime;
  if (getHealth() <= 0F)   worldObj.spawnParticle("String_Node_Str",posX + (rand.nextFloat() - 0.5F) * 8F,posY + 2D + (rand.nextFloat() - 0.5F) * 4F,posZ + (rand.nextFloat() - 0.5F) * 8F,0D,0D,0D);
 else {
    updateEnderCrystal();
    float animAdvance=0.2F / (MathHelper.sqrt_double(motionX * motionX + motionZ * motionZ) * 10F + 1F);
    animAdvance*=(float)Math.pow(2D,motionY);
    animAdvance*=getWingSpeed();
    animTime+=slowed ? animAdvance * 0.5F : animAdvance;
    rotationYaw=MathHelper.wrapAngleTo180_float(rotationYaw);
    if (movementBufferIndex < 0) {
      for (int index=0; index < movementBuffer.length; ++index) {
        movementBuffer[index][0]=rotationYaw;
        movementBuffer[index][1]=posY;
      }
    }
    if (++movementBufferIndex == movementBuffer.length)     movementBufferIndex=0;
    movementBuffer[movementBufferIndex][0]=rotationYaw;
    movementBuffer[movementBufferIndex][1]=posY;
    if (worldObj.isRemote) {
      if (newPosRotationIncrements > 0) {
        double finalPosX=posX + (newPosX - posX) / newPosRotationIncrements, finalPosY=posY + (newPosY - posY) / newPosRotationIncrements, finalPosZ=posZ + (newPosZ - posZ) / newPosRotationIncrements;
        rotationYaw=(float)(rotationYaw + MathHelper.wrapAngleTo180_double(newRotationYaw - rotationYaw) / newPosRotationIncrements);
        rotationPitch=(float)(rotationPitch + (newRotationPitch - rotationPitch) / newPosRotationIncrements);
        --newPosRotationIncrements;
        setPosition(finalPosX,finalPosY,finalPosZ);
        setRotation(rotationYaw,rotationPitch);
      }
    }
 else {
      double xDiff=targetX - posX, yDiff=targetY - posY, zDiff=targetZ - posZ;
      double distFromTargetSq=xDiff * xDiff + yDiff * yDiff + zDiff * zDiff;
      if (target != null) {
        targetX=target.posX;
        targetZ=target.posZ;
        targetY=target.boundingBox.minY + Math.min(0.4D + Math.sqrt(Math.pow(targetX - posX,2) + Math.pow(targetZ - posZ,2)) / 80D - 1D,10D);
      }
 else       trySetTargetPosition(targetX + rand.nextGaussian() * 2D,targetY,targetZ + rand.nextGaussian() * 2D);
      if ((target != null && target.isDead) || distFromTargetSq > 22500D)       forceAttackEnd=forceNewTarget=true;
      if (forceNewTarget || distFromTargetSq < 90D || distFromTargetSq > 22500D || isCollidedHorizontally || isCollidedVertically) {
        setNewTarget();
      }
      yDiff=MathUtil.clamp(yDiff / MathUtil.distance(xDiff,zDiff),-0.6F,0.6F);
      motionY+=yDiff * 0.1D;
      rotationYaw=MathHelper.wrapAngleTo180_float(rotationYaw);
      double d9=MathUtil.clamp(MathHelper.wrapAngleTo180_double(180D - MathUtil.toDeg(Math.atan2(xDiff,zDiff)) - rotationYaw),-50D,50D);
      Vec3 targetDiffVec=Vec3.createVectorHelper(targetX - posX,targetY - posY,targetZ - posZ).normalize();
      Vec3 rotationVec=Vec3.createVectorHelper(MathHelper.sin(MathUtil.toRad(rotationYaw)),motionY,(-MathHelper.cos(MathUtil.toRad(rotationYaw)))).normalize();
      float f4=Math.max((float)(rotationVec.dotProduct(targetDiffVec) + 0.5D) / 1.5F,0F);
      randomYawVelocity*=0.8F;
      float speed=MathHelper.sqrt_double(motionX * motionX + motionZ * motionZ) + 1F;
      double speedLimited=Math.min(Math.sqrt(motionX * motionX + motionZ * motionZ) + 1D,40D);
      randomYawVelocity=(float)(randomYawVelocity + d9 * (0.7D / speedLimited / speed));
      rotationYaw+=randomYawVelocity * 0.1F;
      float f6=(float)(2D / (speedLimited + 1D));
      moveFlying(0F,-1F,0.06F * (f4 * f6 + (1F - f6)));
      if (frozen)       motionX=motionY=motionZ=0D;
      MotionUpdateEvent event=new MotionUpdateEvent(motionX,motionY,motionZ);
      currentAttack.onMotionUpdateEvent(event);
      motionX=event.motionX;
      motionY=event.motionY;
      motionZ=event.motionZ;
      if (slowed)       moveEntity(motionX * moveSpeedMp * 0.8D,motionY * moveSpeedMp * 0.8D,motionZ * moveSpeedMp * 0.8D);
 else       moveEntity(motionX * moveSpeedMp,motionY * moveSpeedMp,motionZ * moveSpeedMp);
      double motionMultiplier=0.8D + 0.15D * ((Vec3.createVectorHelper(motionX,motionY,motionZ).normalize().dotProduct(rotationVec) + 1D) * 0.5D);
      motionX*=motionMultiplier;
      motionZ*=motionMultiplier;
      motionY*=0.91D;
    }
    renderYawOffset=rotationYaw;
    dragonPartHead.width=dragonPartHead.height=3F;
    dragonPartTail1.width=dragonPartTail1.height=2F;
    dragonPartTail2.width=dragonPartTail2.height=2F;
    dragonPartTail3.width=dragonPartTail3.height=2F;
    dragonPartBody.width=5F;
    dragonPartBody.height=3F;
    dragonPartWing1.width=4F;
    dragonPartWing1.height=2F;
    dragonPartWing2.width=4F;
    dragonPartWing2.height=3F;
    float offsetAngle=MathUtil.toRad((float)(getMovementOffsets(5,1F)[1] - getMovementOffsets(10,1F)[1]) * 10F);
    float angleCos=MathHelper.cos(offsetAngle);
    float angleSin=-MathHelper.sin(offsetAngle);
    float yawRad=MathUtil.toRad(rotationYaw);
    float yawSin=MathHelper.sin(yawRad);
    float yawCos=MathHelper.cos(yawRad);
    dragonPartBody.onUpdate();
    dragonPartBody.setLocationAndAngles(posX + yawSin * 0.5F,posY,posZ - yawCos * 0.5F,0F,0F);
    dragonPartWing1.onUpdate();
    dragonPartWing1.setLocationAndAngles(posX + yawCos * 4.5F,posY + 2D,posZ + yawSin * 4.5F,0F,0F);
    dragonPartWing2.onUpdate();
    dragonPartWing2.setLocationAndAngles(posX - yawCos * 4.5F,posY + 2D,posZ - yawSin * 4.5F,0F,0F);
    collideWithEntities(worldObj.getEntitiesWithinAABBExcludingEntity(this,dragonPartWing1.boundingBox.expand(1.5D,2D,1.5D).offset(0D,-2D,0D)));
    collideWithEntities(worldObj.getEntitiesWithinAABBExcludingEntity(this,dragonPartWing2.boundingBox.expand(1.5D,2D,1.5D).offset(0D,-2D,0D)));
    collideWithEntities(worldObj.getEntitiesWithinAABBExcludingEntity(this,dragonPartTail3.boundingBox.expand(0.8D,1D,0.8D)));
    collideWithEntities(worldObj.getEntitiesWithinAABBExcludingEntity(this,dragonPartHead.boundingBox.expand(0.6D,1D,0.6D)));
    double[] oldOffsets=getMovementOffsets(5,1F), currentOffsets=getMovementOffsets(0,1F);
    float moveX=MathHelper.sin(MathUtil.toRad(rotationYaw) - randomYawVelocity * 0.01F);
    float moveZ=MathHelper.cos(MathUtil.toRad(rotationYaw) - randomYawVelocity * 0.01F);
    dragonPartHead.onUpdate();
    dragonPartHead.setLocationAndAngles(posX + moveX * 5.5F * angleCos,posY + currentOffsets[1] - oldOffsets[1] + angleSin * 5.5F,posZ - moveZ * 5.5F * angleCos,0F,0F);
    for (int part=0; part < 3; part++) {
      EntityDragonPart tailPart=part == 0 ? dragonPartTail1 : part == 1 ? dragonPartTail2 : dragonPartTail3;
      double[] partOffsets=getMovementOffsets(12 + part * 2,1F);
      float partYaw=MathUtil.toRad(rotationYaw) + MathUtil.toRad((float)MathHelper.wrapAngleTo180_double(partOffsets[0] - oldOffsets[0]));
      float partYawSin=MathHelper.sin(partYaw);
      float partYawCos=MathHelper.cos(partYaw);
      float partMp=(part + 1) * 2F;
      tailPart.onUpdate();
      tailPart.setLocationAndAngles(posX - ((yawSin * 1.5F + partYawSin * partMp) * angleCos),posY + (partOffsets[1] - oldOffsets[1]) - ((partMp + 1.5F) * angleSin) + 1.5D,posZ + ((yawCos * 1.5F + partYawCos * partMp) * angleCos),0F,0F);
    }
    if (!worldObj.isRemote) {
      slowed=destroyBlocksInAABB(dragonPartHead.boundingBox) | destroyBlocksInAABB(dragonPartBody.boundingBox);
      if (currentAttack.id == 1)       slowed|=destroyBlocksInAABB(dragonPartWing1.boundingBox.expand(0.5D,0.5D,0.5D)) | destroyBlocksInAABB(dragonPartWing2.boundingBox.expand(0.5D,0.5D,0.5D));
      attacks.updatePassiveAttacks(currentAttack);
    }
  }
}