/** Inserts one item from the hopper into the inventory the hopper is pointing at. */
  private boolean insertItemToInventory() {
    IInventory iinventory = this.getOutputInventory();

    if (iinventory == null) {
      return false;
    } else {
      for (int i = 0; i < this.getSizeInventory(); ++i) {
        if (this.getStackInSlot(i) != null) {
          ItemStack itemstack = this.getStackInSlot(i).copy();
          ItemStack itemstack1 =
              insertStack(
                  iinventory,
                  this.decrStackSize(i, 1),
                  Facing.oppositeSide[
                      BlockHopper.getDirectionFromMetadata(this.getBlockMetadata())]);

          if (itemstack1 == null || itemstack1.stackSize == 0) {
            iinventory.onInventoryChanged();
            return true;
          }

          this.setInventorySlotContents(i, itemstack);
        }
      }

      return false;
    }
  }
  @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;
  }
  private static ItemStack func_102014_c(
      IInventory par0IInventory, ItemStack par1ItemStack, int par2, int par3) {
    ItemStack itemstack1 = par0IInventory.getStackInSlot(par2);

    if (canInsertItemToInventory(par0IInventory, par1ItemStack, par2, par3)) {
      boolean flag = false;

      if (itemstack1 == null) {
        int max =
            Math.min(par1ItemStack.getMaxStackSize(), par0IInventory.getInventoryStackLimit());
        if (max >= par1ItemStack.stackSize) {
          par0IInventory.setInventorySlotContents(par2, par1ItemStack);
          par1ItemStack = null;
        } else {
          par0IInventory.setInventorySlotContents(par2, par1ItemStack.splitStack(max));
        }
        flag = true;
      } else if (areItemStacksEqualItem(itemstack1, par1ItemStack)) {
        int max =
            Math.min(par1ItemStack.getMaxStackSize(), par0IInventory.getInventoryStackLimit());
        if (max > itemstack1.stackSize) {
          int l = Math.min(par1ItemStack.stackSize, max - itemstack1.stackSize);
          par1ItemStack.stackSize -= l;
          itemstack1.stackSize += l;
          flag = l > 0;
        }
      }

      if (flag) {
        if (par0IInventory instanceof TileEntityHopper) {
          ((TileEntityHopper) par0IInventory).setTransferCooldown(8);
          par0IInventory.onInventoryChanged();
        }

        par0IInventory.onInventoryChanged();
      }
    }

    return par1ItemStack;
  }
  private static boolean insertStackFromInventory(
      Hopper par0Hopper, IInventory par1IInventory, int par2, int par3) {
    ItemStack itemstack = par1IInventory.getStackInSlot(par2);

    if (itemstack != null && canExtractItemFromInventory(par1IInventory, itemstack, par2, par3)) {
      ItemStack itemstack1 = itemstack.copy();
      ItemStack itemstack2 = insertStack(par0Hopper, par1IInventory.decrStackSize(par2, 1), -1);

      if (itemstack2 == null || itemstack2.stackSize == 0) {
        par1IInventory.onInventoryChanged();
        return true;
      }

      par1IInventory.setInventorySlotContents(par2, itemstack1);
    }

    return false;
  }
  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;
  }