Package forestry.core.utils

Source Code of forestry.core.utils.StackUtils

/*******************************************************************************
* Copyright (c) 2011-2014 SirSengir.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser Public License v3
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/lgpl-3.0.txt
*
* Various Contributors including, but not limited to:
* SirSengir (original work), CovertJaguar, Player, Binnie, MysteriousAges
******************************************************************************/
package forestry.core.utils;

import java.util.ArrayList;
import java.util.Random;

import net.minecraft.block.Block;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.Item;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.world.World;

import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.entity.player.PlayerDestroyItemEvent;
import net.minecraftforge.fluids.FluidContainerRegistry.FluidContainerData;
import net.minecraftforge.oredict.OreDictionary;

import forestry.core.config.Defaults;
import forestry.core.fluids.tanks.StandardTank;
import forestry.core.gadgets.TileForestry;

public class StackUtils {

  public static final ItemStack[] EMPTY_STACK_ARRAY = new ItemStack[0];
  public static final ArrayList<ItemStack> EMPTY_STACK_LIST = new ArrayList<ItemStack>();

  /**
   * Compares item id, damage and NBT. Accepts wildcard damage.
   *
   * @param lhs
   * @param rhs
   * @return
   */
  public static boolean isIdenticalItem(ItemStack lhs, ItemStack rhs) {
    if (lhs == null || rhs == null)
      return false;

    if (lhs.getItem() != rhs.getItem())
      return false;

    if (lhs.getItemDamage() != Defaults.WILDCARD)
      if (lhs.getItemDamage() != rhs.getItemDamage())
        return false;

    return ItemStack.areItemStackTagsEqual(lhs, rhs);
  }

  public static boolean stowInInventory(ItemStack itemstack, IInventory inventory, boolean doAdd) {
    return stowInInventory(itemstack, inventory, doAdd, 0, inventory.getSizeInventory());
  }

  public static boolean stowInInventory(ItemStack itemstack, IInventory inventory, boolean doAdd, int slot1, int count) {

    boolean added = false;

    for (int i = slot1; i < slot1 + count; i++) {
      ItemStack inventoryStack = inventory.getStackInSlot(i);

      // Grab those free slots
      if (inventoryStack == null) {
        if (doAdd) {
          inventory.setInventorySlotContents(i, itemstack.copy());
          itemstack.stackSize = 0;
        }
        return true;
      }

      // Already full
      if (inventoryStack.stackSize >= inventoryStack.getMaxStackSize())
        continue;

      // Not same type
      if (!inventoryStack.isItemEqual(itemstack))
        continue;
      if (!ItemStack.areItemStackTagsEqual(inventoryStack, itemstack))
        continue;

      int space = inventoryStack.getMaxStackSize() - inventoryStack.stackSize;

      // Enough space to add all
      if (space > itemstack.stackSize) {
        if (doAdd) {
          inventoryStack.stackSize += itemstack.stackSize;
          itemstack.stackSize = 0;
        }
        return true;
        // Only part can be added
      } else {
        if (doAdd) {
          inventoryStack.stackSize = inventoryStack.getMaxStackSize();
          itemstack.stackSize -= space;
        }
        added = true;
      }

    }

    return added;

  }

  public static int addToInventory(ItemStack itemstack, IInventory inventory, boolean doAdd, int slot1, int count) {

    int added = 0;

    for (int i = slot1; i < slot1 + count; i++) {
      ItemStack inventoryStack = inventory.getStackInSlot(i);

      // Grab those free slots
      if (inventoryStack == null) {
        if (doAdd)
          inventory.setInventorySlotContents(i, itemstack.copy());
        return itemstack.stackSize;
      }

      // Already full
      if (inventoryStack.stackSize >= inventoryStack.getMaxStackSize())
        continue;

      // Not same type
      if (!inventoryStack.isItemEqual(itemstack))
        continue;

      int space = inventoryStack.getMaxStackSize() - inventoryStack.stackSize;

      // Enough space to add all
      if (space > itemstack.stackSize - added) {
        if (doAdd)
          inventoryStack.stackSize += itemstack.stackSize;
        return itemstack.stackSize;
        // Only part can be added
      } else {
        if (doAdd)
          inventoryStack.stackSize = inventoryStack.getMaxStackSize();
        added += space;
      }

    }

    return added;

  }

  /**
   * Merges the giving stack into the receiving stack as far as possible
   *
   * @param giver
   * @param receptor
   */
  public static void mergeStacks(ItemStack giver, ItemStack receptor) {
    if (receptor.stackSize >= 64)
      return;

    if (!receptor.isItemEqual(giver))
      return;

    if (giver.stackSize <= (receptor.getMaxStackSize() - receptor.stackSize)) {
      receptor.stackSize += giver.stackSize;
      giver.stackSize = 0;
      return;
    }

    ItemStack temp = giver.splitStack(receptor.getMaxStackSize() - receptor.stackSize);
    receptor.stackSize += temp.stackSize;
    temp.stackSize = 0;
    return;
  }

  public static boolean freeSpaceInStack(ItemStack stack, int maxSize) {
    if (stack == null)
      return true;

    if (stack.stackSize >= maxSize)
      return false;

    return true;
  }

  /**
   * Creates a split stack of the specified amount, preserving NBT data,
   * without decreasing the source stack.
   *
   * @param stack
   * @param amount
   * @return
   */
  public static ItemStack createSplitStack(ItemStack stack, int amount) {
    ItemStack split = new ItemStack(stack.getItem(), amount, stack.getItemDamage());
    if (stack.getTagCompound() != null) {
      NBTTagCompound nbttagcompound = (NBTTagCompound) stack.getTagCompound().copy();
      split.setTagCompound(nbttagcompound);
    }
    return split;
  }

  public static ItemStack[] condenseStacks(ItemStack[] stacks) {
    return condenseStacks(stacks, -1, false);
  }

  /**
   *
   * @param stacks
   * @param maxCountedPerStack The maximum stacksize counted in a single
   * stack. -1 for unlimited.
   * @return
   */
  public static ItemStack[] condenseStacks(ItemStack[] stacks, int maxCountedPerStack, boolean craftingEquivalency) {
    ArrayList<ItemStack> condensed = new ArrayList<ItemStack>();

    for (ItemStack stack : stacks) {
      if (stack == null)
        continue;
      if (stack.stackSize <= 0)
        continue;

      boolean matched = false;
      for (ItemStack cached : condensed) {
        if (cached.isItemEqual(stack)
            || (craftingEquivalency && isCraftingEquivalent(cached, stack, true, false))) {
          cached.stackSize += maxCountedPerStack > 0 && stack.stackSize > maxCountedPerStack ? maxCountedPerStack : stack.stackSize;
          matched = true;
        }
      }

      if (!matched) {
        ItemStack cached = stack.copy();
        if (maxCountedPerStack > 0)
          cached.stackSize = maxCountedPerStack;
        condensed.add(cached);
      }

    }

    return condensed.toArray(EMPTY_STACK_ARRAY);
  }

  /**
   * Counts how many full sets are contained in the passed stock
   *
   * @param set
   * @param stock
   * @return
   */
  public static int containsSets(ItemStack[] set, ItemStack[] stock) {
    return containsSets(set, stock, false, false);
  }

  /**
   * Counts how many full sets are contained in the passed stock
   *
   * @param set
   * @param stock
   * @return
   */
  public static int containsSets(ItemStack[] set, ItemStack[] stock, boolean oreDictionary, boolean craftingTools) {
    int count = 0;

    ItemStack[] condensedRequired = StackUtils.condenseStacks(set, -1, oreDictionary);
    ItemStack[] condensedOffered = StackUtils.condenseStacks(stock, -1, oreDictionary);

    for (ItemStack req : condensedRequired) {

      boolean matched = false;
      for (ItemStack offer : condensedOffered) {

        if (isCraftingEquivalent(req, offer, oreDictionary, craftingTools)) {
          matched = true;

          int stackCount = (int) Math.floor(offer.stackSize / req.stackSize);
          if (stackCount <= 0)
            return 0;
          else if (count == 0)
            count = stackCount;
          else if (count > stackCount)
            count = stackCount;
        }
      }
      if (!matched)
        return 0;
    }

    return count;
  }

  /**
   * Compare two item stacks for crafting equivalency without oreDictionary or craftingTools
   */
  public static boolean isCraftingEquivalent(ItemStack base, ItemStack comparison) {
    if (base == null || comparison == null)
      return false;

    if (base.getItem() != comparison.getItem())
      return false;

    if (base.getItemDamage() != Defaults.WILDCARD)
      if (base.getItemDamage() != comparison.getItemDamage())
        return false;

    // When the base stackTagCompound is null or empty, treat it as a wildcard for crafting
    if (base.stackTagCompound == null || base.stackTagCompound.hasNoTags())
      return true;
    else
      return ItemStack.areItemStackTagsEqual(base, comparison);
  }

  /**
   * Compare two item stacks for crafting equivalency.
   *
   * @param base
   * @param comparison
   * @param oreDictionary
   * @return
   */
  public static boolean isCraftingEquivalent(ItemStack base, ItemStack comparison, boolean oreDictionary, boolean craftingTools) {
    if (isCraftingEquivalent(base, comparison))
      return true;

    if (base == null || comparison == null)
      return false;

    if (oreDictionary) {
      int[] idsBase = OreDictionary.getOreIDs(base);
      for (int idBase : idsBase) {
        for (ItemStack itemstack : OreDictionary.getOres(OreDictionary.getOreName(idBase))) {
          if (comparison.getItem() == itemstack.getItem() && (itemstack.getItemDamage() == OreDictionary.WILDCARD_VALUE || comparison.getItemDamage() == itemstack.getItemDamage()))
            return true;
        }
      }
    }

    if (craftingTools) {
      return isThisCraftingTool(base, comparison);
    }

    return false;
  }

  public static boolean isCraftingTool(ItemStack itemstack) {
    return itemstack.getItem().hasContainerItem(itemstack)
        && itemstack.getItem().isDamageable()
        && !itemstack.getItem().doesContainerItemLeaveCraftingGrid(itemstack);
  }

  public static boolean isThisCraftingTool(ItemStack phantom, ItemStack actual) {
    return isCraftingTool(phantom) && phantom.getItem() == actual.getItem();
  }

  public static void stowContainerItem(ItemStack itemstack, InventoryAdapter stowing, int slotIndex, EntityPlayer player) {
    if (!itemstack.getItem().hasContainerItem(itemstack))
      return;

    ItemStack container = itemstack.getItem().getContainerItem(itemstack);

    if (container.isItemStackDamageable() && container.getItemDamage() > container.getMaxDamage()) {
      MinecraftForge.EVENT_BUS.post(new PlayerDestroyItemEvent(player, container));
      container = null;
    }

    if (container != null) {

      if (itemstack.getItem().doesContainerItemLeaveCraftingGrid(itemstack)) {
        if (!stowing.tryAddStack(container, true))
          if (!player.inventory.addItemStackToInventory(container))
            player.dropPlayerItemWithRandomChoice(container, true);
      } else {
        if (!stowing.tryAddStack(container, slotIndex, 1, true))
          if (!stowing.tryAddStack(container, true))
            player.dropPlayerItemWithRandomChoice(container, true);
      }
    }
  }

  public static void dropItemStackAsEntity(ItemStack items, World world, double x, double y, double z) {
    if (items.stackSize <= 0)
      return;

    float f1 = 0.7F;
    double d = (world.rand.nextFloat() * f1) + (1.0F - f1) * 0.5D;
    double d1 = (world.rand.nextFloat() * f1) + (1.0F - f1) * 0.5D;
    double d2 = (world.rand.nextFloat() * f1) + (1.0F - f1) * 0.5D;
    EntityItem entityitem = new EntityItem(world, x + d, y + d1, z + d2, items);
    entityitem.delayBeforeCanPickup = 10;

    world.spawnEntityInWorld(entityitem);

  }

  public static void replenishByContainer(TileForestry tile, ItemStack inventoryStack, StandardTank tank) {
    FluidContainerData container = LiquidHelper.getLiquidContainer(inventoryStack);
    replenishByContainer(tile, inventoryStack, container, tank);
  }

  public static ItemStack replenishByContainer(TileForestry tile, ItemStack inventoryStack, FluidContainerData container, StandardTank tank) {
    if (container == null)
      return inventoryStack;

    if (tank.fill(container.fluid, false) >= container.fluid.amount) {
      tank.fill(container.fluid, true);
      if (container.filledContainer != null && container.filledContainer.getItem().hasContainerItem(container.filledContainer))
        inventoryStack = container.emptyContainer.copy();
      else
        inventoryStack.stackSize--;
      tile.sendNetworkUpdate();
    }

    return inventoryStack;
  }

  public static ItemStack copyWithRandomSize(ItemStack template, int max, Random rand) {
    int size = rand.nextInt(max);
    ItemStack created = template.copy();
    created.stackSize = size <= 0 ? 1 : size > created.getMaxStackSize() ? created.getMaxStackSize() : size;
    return created;
  }

  public static ItemStack consumeItem(ItemStack stack) {
    if (stack.stackSize == 1) {
      if (stack.getItem().hasContainerItem(stack)) {
        return stack.getItem().getContainerItem(stack);
      } else {
        return null;
      }
    } else {
      stack.splitStack(1);

      return stack;
    }
  }

  public static Block getBlock(ItemStack stack) {
    Item item = stack.getItem();

    if (item instanceof ItemBlock) {
      return ((ItemBlock) item).field_150939_a;
    } else {
      return null;
    }
  }

  public static boolean equals(Block block, ItemStack stack) {
    return block == getBlock(stack);
  }
}
TOP

Related Classes of forestry.core.utils.StackUtils

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.