@Override
  public boolean canPlaceBlockOnSide(World world, int x, int y, int z, int side) {

    if (!canPlaceBlockAt(world, x, y, z)) return false;
    BlockPosition bp =
        new BlockPosition(x, y, z, ForgeDirection.getOrientation(side)).moveBackwards(1);
    return bp.getBlock(world).isSideSolid(world, bp.x, bp.y, bp.z, bp.orientation);
  }
  private BlockPosition getNextTreeSegment(BlockPosition pos) {
    Block block;

    if (_treeManager.getIsDone() || !_treeManager.getOrigin().equals(pos)) {
      int lowerBound = 0;
      int upperBound = MFRConfig.fruitTreeSearchMaxVertical.getInt();

      Area a =
          new Area(
              pos.copy(), MFRConfig.fruitTreeSearchMaxHorizontal.getInt(), lowerBound, upperBound);

      _treeManager.reset(worldObj, a, HarvestMode.FruitTree, null);
    }

    Map<Block, IFactoryFruit> fruits = MFRRegistry.getFruits();
    while (!_treeManager.getIsDone()) {
      BlockPosition bp = _treeManager.getNextBlock();
      block = worldObj.getBlock(bp.x, bp.y, bp.z);
      IFactoryFruit fruit = fruits.containsKey(block) ? fruits.get(block) : null;

      if (fruit != null && fruit.canBePicked(worldObj, bp.x, bp.y, bp.z)) return bp;

      _treeManager.moveNext();
    }
    return null;
  }
  @Override
  public boolean canBlockStay(World world, int x, int y, int z) {

    if (world.isSideSolid(x, y - 1, z, ForgeDirection.UP)) {
      return true;
    }
    for (ForgeDirection d : _attachDirections) {
      BlockPosition bp = new BlockPosition(x, y, z, d);
      for (int i = 0; i < _attachDistance; i++) {
        bp.moveForwards(1);
        if (world.getBlock(bp.x, bp.y, bp.z).equals(this)) {
          if (world.isSideSolid(bp.x, bp.y - 1, bp.z, ForgeDirection.UP)) {
            return true;
          }
        } else break;
      }
    }
    return false;
  }
  @Override
  public void onNeighborBlockChange(World world, int x, int y, int z, Block block) {

    if (!canBlockStay(world, x, y, z)) {
      for (int e = world.getActualHeight(); y < e; ++y) {
        block = world.getBlock(x, y, z);
        if (!block.equals(this)) break;
        dropBlockAsItem(world, x, y, z, world.getBlockMetadata(x, y, z), 0);
        world.setBlock(x, y, z, Blocks.air, 0, 2);
        for (ForgeDirection d : _attachDirections) {
          BlockPosition bp = new BlockPosition(x, y, z, d);
          for (int i = 0; i < _attachDistance; i++) {
            bp.moveForwards(1);
            block = world.getBlock(bp.x, bp.y, bp.z);
            if (block.equals(this)) {
              world.func_147446_b(bp.x, bp.y, bp.z, block, 0, 0);
            } else break;
          }
        }
      }
    }
  }