@Override
  public void positionReached(EntityMechanicalArm arm) {
    inProcess = false;

    if (worldObj.isRemote) {
      return;
    }

    double[] targ = arm.getTarget();
    targetX = (int) targ[0];
    targetY = (int) targ[1];
    targetZ = (int) targ[2];

    int i = targetX;
    int j = targetY - 1;
    int k = targetZ;

    int blockId = worldObj.getBlockId(i, j, k);

    if (isQuarriableBlock(blockId, i, j, k)) {
      powerProvider.getTimeTracker().markTime(worldObj);

      // Share this with mining well!

      ArrayList<ItemStack> stacks = BuildCraftBlockUtil.getItemStackFromBlock(worldObj, i, j, k);

      if (stacks != null) {
        for (ItemStack s : stacks) {
          if (s != null) {
            mineStack(s);
          }
        }
      }

      worldObj.setBlockWithNotify(i, j, k, 0);
    }

    // Collect any lost items laying around
    double[] armHead = arm.getHead();
    AxisAlignedBB axis =
        AxisAlignedBB.getBoundingBox(
            armHead[0] - 1.5,
            armHead[1],
            armHead[2] - 1.5,
            armHead[0] + 2.5,
            armHead[1] + 2.5,
            armHead[2] + 2.5);
    List result = worldObj.getEntitiesWithinAABB(EntityItem.class, axis);
    for (int ii = 0; ii < result.size(); ii++) {
      if (result.get(ii) instanceof EntityItem) {
        EntityItem entity = (EntityItem) result.get(ii);
        if (entity.isDead) continue;
        if (entity.item.stackSize <= 0) continue;
        ProxyCore.proxy.removeEntity(entity);
        mineStack(entity.item);
      }
    }
  }
  @Override
  public void postPacketHandling(PacketUpdate packet) {

    super.postPacketHandling(packet);

    createUtilsIfNeeded();
    //
    if (arm != null) {
      arm.setHead(headPosX, headPosY, headPosZ);
      //			arm.setTarget(targetX, targetY, targetZ);
      //			arm.setArmSpeed(speed);
    }
  }
  @Override
  public void destroy() {

    if (arm != null) {
      arm.setDead();
    }

    if (builder != null) {
      builder.setDead();
    }

    box.deleteLasers();
    arm = null;
  }
  protected void dig() {

    powerProvider.configure(20, 30, 200, 50, MAX_ENERGY);
    if (powerProvider.useEnergy(30, 30, true) != 30) {
      return;
    }

    if (!findTarget(true)) {

      // I believe the issue is box going null becuase of bad chunkloader positioning
      if (arm != null && box != null)
        arm.setTarget(
            (double) box.xMin + (box.xMax - box.xMin) / 2D,
            yCoord + 2D,
            (double) box.zMin + (box.zMax - box.zMin) / 2D);

      isDigging = false;
    }

    inProcess = true;
  }
  public boolean findTarget(boolean doSet) {

    if (worldObj.isRemote) return false;

    boolean[][] blockedColumns =
        new boolean[bluePrintBuilder.bluePrint.sizeX - 2][bluePrintBuilder.bluePrint.sizeZ - 2];

    //		for (int searchX = 0; searchX < bluePrintBuilder.bluePrint.sizeX - 2; ++searchX) {
    //			for (int searchZ = 0; searchZ < bluePrintBuilder.bluePrint.sizeZ - 2; ++searchZ) {
    //				blockedColumns[searchX][searchZ] = false;
    //			}
    //		}
    //
    for (int searchY = yCoord + 3; searchY >= 0; --searchY) {
      int startX, endX, incX;

      if (searchY % 2 == 0) {
        startX = 0;
        endX = bluePrintBuilder.bluePrint.sizeX - 2;
        incX = 1;
      } else {
        startX = bluePrintBuilder.bluePrint.sizeX - 3;
        endX = -1;
        incX = -1;
      }

      for (int searchX = startX; searchX != endX; searchX += incX) {
        int startZ, endZ, incZ;

        if (searchX % 2 == searchY % 2) {
          startZ = 0;
          endZ = bluePrintBuilder.bluePrint.sizeZ - 2;
          incZ = 1;
        } else {
          startZ = bluePrintBuilder.bluePrint.sizeZ - 3;
          endZ = -1;
          incZ = -1;
        }

        for (int searchZ = startZ; searchZ != endZ; searchZ += incZ) {
          if (!blockedColumns[searchX][searchZ]) {
            int bx = box.xMin + searchX + 1, by = searchY, bz = box.zMin + searchZ + 1;

            int blockId = worldObj.getBlockId(bx, by, bz);

            if (isUnquarriableBlock(blockId, bx, by, bz)) {
              blockedColumns[searchX][searchZ] = true;
            } else if (isQuarriableBlock(blockId, bx, by + 1, bz)) {
              if (doSet && arm != null) {
                arm.setTarget(bx, by + 1, bz);
              }

              return true;
            }
          }
        }
      }
    }

    return false;
  }
  @Override
  public void updateEntity() {
    super.updateEntity();

    if (inProcess && arm != null) {

      arm.setArmSpeed(0);
      float energyToUse = 2 + powerProvider.getEnergyStored() / 1000;

      boolean enoughStep =
          (0.015 + energyToUse / 200F)
              > (1F
                  / 32F); // (otherwise the movement is rounded to 0 and the energy absorbed with no
                          // movement)
      if (enoughStep) {
        float energy = powerProvider.useEnergy(energyToUse, energyToUse, true);

        if (energy > 0) {
          arm.doMove(0.015 + energy / 200F);
        }
      }
    }

    if (arm != null) {
      double[] head = arm.getHead();
      headPosX = head[0];
      headPosY = head[1];
      headPosZ = head[2];

      speed = arm.getArmSpeed();
    }

    if (ProxyCore.proxy.isSimulating(worldObj)) {
      sendNetworkUpdate();
    }
    if (inProcess || !isDigging) {
      return;
    }

    createUtilsIfNeeded();

    if (bluePrintBuilder != null) {

      builderDone = bluePrintBuilder.done;
      if (!builderDone) {

        buildFrame();
        return;

      } else {

        if (builder != null && builder.done()) {

          box.deleteLasers();
          builder.setDead();
          builder = null;
        }
      }
    }

    if (builder == null) {
      dig();
    }
  }
 // Callback from the arm once it's created
 public void setArm(EntityMechanicalArm arm) {
   this.arm = arm;
   arm.listener = this;
   isDigging = true;
 }