@Override
  public ItemStack pullItem(ForgeDirection side, boolean doPull) {
    int xo = xCoord + side.offsetX;
    int yo = yCoord + side.offsetY;
    int zo = zCoord + side.offsetZ;

    TileEntity t = worldObj.getBlockTileEntity(xo, yo, zo);

    if (t instanceof IInventory) {
      if (t instanceof ISpecialInventory) {
        ISpecialInventory isi = (ISpecialInventory) t;
        ItemStack[] items = isi.extractItem(doPull, side.getOpposite(), 1);
        if (items != null && items.length > 0) return items[0];
      } else if (t instanceof ISidedInventory) {
        ISidedInventory isi = (ISidedInventory) t;
        int[] slots = isi.getAccessibleSlotsFromSide(side.getOpposite().ordinal());

        for (int i = 0; i < slots.length; i++) {
          ItemStack pulled = isi.getStackInSlot(slots[i]);
          if (pulled != null
              && isi.canExtractItem(slots[i], pulled, side.getOpposite().ordinal())) {
            ItemStack result = null; // pulled.copy().splitStack(1);
            // pulled.stackSize--;
            // isi.setInventorySlotContents(slots[i], pulled);
            // if(pulled.stackSize <= 0) isi.setInventorySlotContents(slots[i], null);
            if (doPull) {
              result = isi.decrStackSize(slots[i], 1);
              isi.onInventoryChanged();
            } else {
              result = pulled.copy().splitStack(1);
            }
            return result;
          }
        }
      } else {
        IInventory ii = (IInventory) t;

        for (int i = 0; i < ii.getSizeInventory(); i++) {
          ItemStack pulled = ii.getStackInSlot(i);
          if (pulled != null) {
            ItemStack result = null;
            // pulled.stackSize--;
            // ii.setInventorySlotContents(i, pulled);
            // if(pulled.stackSize <= 0)ii.setInventorySlotContents(i, null);
            if (doPull) {
              result = ii.decrStackSize(i, 1);
              ii.onInventoryChanged();
            } else {
              result = pulled.copy().splitStack(1);
            }
            return result;
          }
        }
      }
    }

    return null;
  }
  public boolean tryInsertItem(ItemStack stack, ForgeDirection side) {
    int xo = xCoord + side.offsetX;
    int yo = yCoord + side.offsetY;
    int zo = zCoord + side.offsetZ;

    TileEntity t = worldObj.getBlockTileEntity(xo, yo, zo);

    if (stack == null) return false;

    if (t instanceof IInventory) {
      if (t instanceof ISpecialInventory) {
        ISpecialInventory isi = (ISpecialInventory) t;
        ItemStack ghost = stack.copy().splitStack(1);
        int used = isi.addItem(ghost, true, side.getOpposite());
        if (used > 0) return true;

      } else if (t instanceof ISidedInventory) {
        ISidedInventory isi = (ISidedInventory) t;
        ItemStack ghost = stack.copy().splitStack(1);
        int[] slots = isi.getAccessibleSlotsFromSide(side.getOpposite().ordinal());

        for (int i = 0; i < slots.length; i++) {
          if (isi.canInsertItem(slots[i], ghost, side.getOpposite().ordinal())) {
            ItemStack inSlot = isi.getStackInSlot(slots[i]);
            if (inSlot != null
                && inSlot.isItemEqual(ghost)
                && inSlot.stackSize < inSlot.getMaxStackSize()
                && inSlot.stackSize < isi.getInventoryStackLimit()) {
              inSlot.stackSize++;
              isi.onInventoryChanged();
              return true;
            }
          }
        }

        for (int i = 0; i < slots.length; i++) {
          if (isi.canInsertItem(slots[i], ghost, side.getOpposite().ordinal())) {
            ItemStack inSlot = isi.getStackInSlot(slots[i]);
            if (inSlot == null) {
              isi.setInventorySlotContents(slots[i], ghost);
              isi.onInventoryChanged();
              return true;
            }
          }
        }

        return false;
      } else {
        IInventory ii = (IInventory) t;
        ItemStack ghost = stack.copy().splitStack(1);

        for (int i = 0; i < ii.getSizeInventory(); i++) {
          if (ii.isItemValidForSlot(i, ghost)) {
            ItemStack inSlot = ii.getStackInSlot(i);
            if (inSlot != null
                && inSlot.isItemEqual(ghost)
                && inSlot.stackSize < inSlot.getMaxStackSize()
                && inSlot.stackSize < ii.getInventoryStackLimit()) {
              inSlot.stackSize++;
              ii.onInventoryChanged();
              return true;
            }
          }
        }

        for (int i = 0; i < ii.getSizeInventory(); i++) {
          if (ii.isItemValidForSlot(i, ghost)) {
            ItemStack inSlot = ii.getStackInSlot(i);
            if (inSlot == null) {
              ii.setInventorySlotContents(i, ghost);
              ii.onInventoryChanged();
              return true;
            }
          }
        }

        return false;
      }
    }

    if (Loader.isModLoaded("BuildCraft|Core") && t != null && stack != null) {
      if (t instanceof IPipeTile) {
        IPipeTile p = (IPipeTile) t;

        if (p.getPipeType() == PipeType.ITEM && p.isPipeConnected(side.getOpposite())) {
          int res = p.injectItem(stack, false, side.getOpposite());
          if (res == stack.stackSize) {
            p.injectItem(stack, true, side.getOpposite());
            stack.stackSize = 0;
            return true;
          }
        }
      }
    }

    return false;
  }