public static boolean itemsEqualForCrafting(final ItemStack stack1, final ItemStack stack2) {
   return areEqualNoMeta(stack1, stack2)
       && (!stack1.getHasSubtypes()
           || OreDictionaryHelper.isGeneric(stack1)
           || OreDictionaryHelper.isGeneric(stack2)
           || getItemDamage(stack2) == getItemDamage(stack1));
 }
  public static Optional<ItemStack> convertToDustIfPossible(final ItemStack stack) {

    String oreName = OreDictionaryHelper.getOreName(stack);

    if (oreName == null) return Optional.of(stack);

    if (oreName.startsWith("ingot")) oreName = StringUtils.replaceOnce(oreName, "ingot", "dust");
    else if (oreName.startsWith("plank"))
      oreName = StringUtils.replaceOnce(oreName, "plank", "dust");
    else return Optional.of(stack);

    return getItemStack(oreName);
  }
  public static Optional<ItemStack> getPreferredStack(final ItemStack stack) {
    final String oreName = OreDictionaryHelper.getOreName(stack);
    if (oreName == null || oreName.isEmpty() || "Unknown".compareToIgnoreCase(oreName) == 0)
      return Optional.of(stack);

    Optional<ItemStack> newStack = getItemStack(oreName);
    if (newStack.isPresent()) {
      final ItemStack result = newStack.get();
      result.stackSize = stack.stackSize;
      newStack = Optional.of(result);
    }

    return newStack;
  }
  public static Optional<ItemStack> getItemStack(final String name, final int quantity) {

    if (name == null || name.isEmpty()) return Optional.absent();

    // Check our preferred list first. If we have a hit, use it.
    ItemStack result = PreferredItemStacks.instance.get(name);

    if (result != null) {

      result = result.copy();
      result.stackSize = quantity;

    } else {

      // Parse out the possible subtype from the end of the string
      String workingName = name;
      int subType = -1;

      if (StringUtils.countMatches(name, ":") == 2) {
        workingName = StringUtils.substringBeforeLast(name, ":");
        final String num = StringUtils.substringAfterLast(name, ":");

        if (num != null && !num.isEmpty()) {

          if ("*".compareTo(num) == 0) subType = OreDictionaryHelper.WILDCARD_VALUE;
          else {
            try {
              subType = Integer.parseInt(num);
            } catch (Exception e) {
              // It appears malformed - assume the incoming name
              // is
              // the real name and continue.
              ;
            }
          }
        }
      }

      // Check the OreDictionary first for any alias matches. Otherwise
      // go to the game registry to find a match.
      final List<ItemStack> ores = OreDictionaryHelper.getOres(workingName);
      if (!ores.isEmpty()) {
        result = ores.get(0).copy();
        result.stackSize = quantity;
      } else {
        final Item i = GameData.getItemRegistry().getObject(workingName);
        if (i != null) {
          result = new ItemStack(i, quantity);
        }
      }

      // If we did have a hit on a base item, set the sub-type
      // as needed.
      if (result != null && subType != -1) {
        if (subType == OreDictionaryHelper.WILDCARD_VALUE && !result.getHasSubtypes()) {
          ModLog.warn("[%s] GENERIC requested but Item does not support sub-types", name);
        } else {
          result.setItemDamage(subType);
        }
      }
    }

    return Optional.fromNullable(result);
  }