public void update(double posX, double posY, double posZ) {
    setOldMinigunRotation(getMinigunRotation());
    oldMinigunYaw = minigunYaw;
    oldMinigunPitch = minigunPitch;
    if (attackTarget != null && attackTarget.isDead) attackTarget = null;
    if (!world.isRemote) {
      setMinigunActivated(getMinigunTriggerTimeOut() > 0);

      setAmmoColorStack(ammo);

      if (getMinigunTriggerTimeOut() > 0) {
        setMinigunTriggerTimeOut(getMinigunTriggerTimeOut() - 1);
        if (getMinigunSpeed() == 0) {
          playSound(Sounds.HUD_INIT, 2, 0.9F);
        }
      }
      if (getMinigunSoundCounter() == 0 && getMinigunTriggerTimeOut() == 0) {
        playSound(Sounds.MINIGUN_STOP, 3, 0.5F);
        setMinigunSoundCounter(-1);
      }
    }
    if (isMinigunActivated()) {
      setMinigunSpeed(Math.min(getMinigunSpeed() + 0.01D, MAX_GUN_SPEED));
    } else {
      setMinigunSpeed(Math.max(0, getMinigunSpeed() - 0.003D));
    }

    setMinigunRotation(getMinigunRotation() + getMinigunSpeed());

    double targetYaw = 0;
    double targetPitch = 0;
    if (attackTarget != null) {
      double deltaX = posX - attackTarget.posX;
      double deltaZ = posZ - attackTarget.posZ;

      if (deltaX >= 0 && deltaZ < 0) {
        targetYaw = Math.atan(Math.abs(deltaX / deltaZ)) / Math.PI * 180D;
      } else if (deltaX >= 0 && deltaZ >= 0) {
        targetYaw = Math.atan(Math.abs(deltaZ / deltaX)) / Math.PI * 180D + 90;
      } else if (deltaX < 0 && deltaZ >= 0) {
        targetYaw = Math.atan(Math.abs(deltaX / deltaZ)) / Math.PI * 180D + 180;
      } else {
        targetYaw = Math.atan(Math.abs(deltaZ / deltaX)) / Math.PI * 180D + 270;
      }
      if (targetYaw - minigunYaw > 180) {
        targetYaw -= 360;
      } else if (minigunYaw - targetYaw > 180) {
        targetYaw += 360;
      }
      targetPitch =
          Math.toDegrees(
              Math.atan(
                  (posY - attackTarget.posY - attackTarget.height / 2)
                      / PneumaticCraftUtils.distBetween(
                          posX, posZ, attackTarget.posX, attackTarget.posZ)));

      if (minigunPitch > targetPitch) {
        if (minigunPitch - MAX_GUN_PITCH_CHANGE > targetPitch) {
          minigunPitch -= MAX_GUN_PITCH_CHANGE;
        } else {
          minigunPitch = targetPitch;
        }
      } else {
        if (minigunPitch + MAX_GUN_PITCH_CHANGE < targetPitch) {
          minigunPitch += MAX_GUN_PITCH_CHANGE;
        } else {
          minigunPitch = targetPitch;
        }
      }

      if (minigunPitch < -80 || minigunPitch > 80) {
        minigunYaw = targetYaw;
      } else {
        if (minigunYaw > targetYaw) {
          if (minigunYaw - MAX_GUN_YAW_CHANGE > targetYaw) {
            minigunYaw -= MAX_GUN_YAW_CHANGE;
          } else {
            minigunYaw = targetYaw;
          }
        } else {
          if (minigunYaw + MAX_GUN_YAW_CHANGE < targetYaw) {
            minigunYaw += MAX_GUN_YAW_CHANGE;
          } else {
            minigunYaw = targetYaw;
          }
        }
      }
      gunAimedAtTarget = minigunYaw == targetYaw && minigunPitch == targetPitch;
    } else if (isSweeping()) {
      minigunYaw -= Math.cos(sweepingProgress) * 22;
      sweepingProgress += 0.05D;
      minigunYaw += Math.cos(sweepingProgress) * 22;

      if (minigunPitch > targetPitch) {
        if (minigunPitch - MAX_GUN_PITCH_CHANGE > targetPitch) {
          minigunPitch -= MAX_GUN_PITCH_CHANGE;
        } else {
          minigunPitch = targetPitch;
        }
      } else {
        if (minigunPitch + MAX_GUN_PITCH_CHANGE < targetPitch) {
          minigunPitch += MAX_GUN_PITCH_CHANGE;
        } else {
          minigunPitch = targetPitch;
        }
      }
    }

    if (!world.isRemote
        && isMinigunActivated()
        && getMinigunSpeed() == MAX_GUN_SPEED
        && (!requiresTarget || gunAimedAtTarget && attackTarget != null)) {
      if (getMinigunSoundCounter() <= 0) {
        playSound(Sounds.MINIGUN, 0.3F, 1);
        setMinigunSoundCounter(20);
      }
    }
    if (getMinigunSoundCounter() > 0) setMinigunSoundCounter(getMinigunSoundCounter() - 1);
  }
  @Override
  public void updateEntity() {

    super.updateEntity();

    oldCurX = curX;
    oldCurY = curY;
    oldCurZ = curZ;
    if (PneumaticCraftUtils.distBetween(getPosition(), targetX, targetY, targetZ) <= getSpeed()) {
      curX = targetX;
      curY = targetY;
      curZ = targetZ;
    } else {
      Vec3 vec =
          Vec3.createVectorHelper(targetX - curX, targetY - curY, targetZ - curZ).normalize();
      curX += vec.xCoord * getSpeed();
      curY += vec.yCoord * getSpeed();
      curZ += vec.zCoord * getSpeed();
    }

    if (!worldObj.isRemote) {
      getAIManager();
      if (worldObj.getTotalWorldTime() % 40 == 0) {
        dispenserUpgrades = getUpgrades(ItemMachineUpgrade.UPGRADE_DISPENSER_DAMAGE);
        speedUpgrades = getUpgrades(ItemMachineUpgrade.UPGRADE_SPEED_DAMAGE);

        for (int i = getDroneSlots(); i < 36; i++) {
          ItemStack stack = getFakePlayer().inventory.getStackInSlot(i);
          if (stack != null) {
            worldObj.spawnEntityInWorld(
                new EntityItem(worldObj, xCoord + 0.5, yCoord + 1.5, zCoord + 0.5, stack));
            getFakePlayer().inventory.setInventorySlotContents(i, null);
          }
        }

        tank.setCapacity((dispenserUpgrades + 1) * 16000);
        if (tank.getFluidAmount() > tank.getCapacity()) {
          tank.getFluid().amount = tank.getCapacity();
        }
      }
      for (int i = 0; i < 4; i++) {
        getFakePlayer().theItemInWorldManager.updateBlockRemoving();
      }
      if (getPressure(ForgeDirection.UNKNOWN) >= getMinWorkingPressure()) {
        if (!aiManager.isIdling()) addAir(-10, ForgeDirection.UNKNOWN);
        aiManager.onUpdateTasks();
      }
    } else {
      if (drone == null || drone.isDead) {
        drone = new EntityProgrammableController(worldObj, this);
        drone.posX = curX;
        drone.posY = curY;
        drone.posZ = curZ;
        worldObj.spawnEntityInWorld(drone);
      }
      drone.setPosition(curX, curY, curZ);
      // drone.getMoveHelper().setMoveTo(curX, curY, curZ, 0);
      /*   drone.prevPosX = oldCurX;
      drone.prevPosY = oldCurY;
      drone.prevPosZ = oldCurZ;*/
      // drone.getMoveHelper().setMoveTo(curX, curY, curZ, getSpeed());
    }
  }