public static boolean doMinecartCollection(final MinecartManiaMinecart minecart) {
    if (minecart.getBlockTypeAhead() != null) {
      if (minecart.getBlockTypeAhead().getType().getId() == Material.CHEST.getId()) {
        final MinecartManiaChest chest =
            MinecartManiaWorld.getMinecartManiaChest(
                (Chest) minecart.getBlockTypeAhead().getState());

        if (SignCommands.isNoCollection(chest)) return false;

        if (minecart instanceof MinecartManiaStorageCart) {
          final MinecartManiaStorageCart storageCart = (MinecartManiaStorageCart) minecart;
          boolean failed = false;
          for (final ItemStack item : storageCart.getInventory().getContents()) {
            if (!chest.addItem(item)) {
              failed = true;
              break;
            }
          }
          if (!failed) {
            storageCart.getInventory().clear();
          }
        }
        if (chest.addItem(minecart.getType().getId())) {

          minecart.kill(false);
          return true;
        }
      }
    }
    return false;
  }
 public static void createItemContainers(
     MinecartManiaStorageCart minecart, HashSet<ComparableLocation> available) {
   ArrayList<ItemContainer> containers = new ArrayList<ItemContainer>();
   for (Location loc : available) {
     Sign sign = (Sign) loc.getBlock().getState();
     if (isItemCollectionSign(sign)) {
       MinecartManiaLogger.getInstance().debug("Found Collect Item Sign");
       bracketizeSign(sign);
       containers.addAll(
           getItemContainers(sign.getBlock().getLocation(), minecart.getDirection(), true));
     } else if (isItemDepositSign(sign)) {
       MinecartManiaLogger.getInstance().debug("Found Deposit Item Sign");
       bracketizeSign(sign);
       containers.addAll(
           getItemContainers(sign.getBlock().getLocation(), minecart.getDirection(), false));
     } else if (isTrashItemSign(sign)) {
       MinecartManiaLogger.getInstance().debug("Found Trash Item Sign");
       bracketizeSign(sign);
       containers.addAll(
           getTrashItemContainers(sign.getBlock().getLocation(), minecart.getDirection()));
     }
     containers.addAll(
         getFurnaceContainers(sign.getBlock().getLocation(), minecart.getDirection()));
   }
   minecart.setDataValue("ItemContainerList", containers);
 }
 @SuppressWarnings("unchecked")
 public static void updateContainerDirections(MinecartManiaStorageCart minecart) {
   ArrayList<ItemContainer> containers =
       (ArrayList<ItemContainer>) minecart.getDataValue("ItemContainerList");
   if (containers != null) {
     for (ItemContainer container : containers) {
       container.addDirection(minecart.getDirectionOfMotion());
     }
   }
 }
 @SuppressWarnings("unchecked")
 public static void processItemContainer(MinecartManiaStorageCart minecart) {
   ArrayList<ItemContainer> containers =
       (ArrayList<ItemContainer>) minecart.getDataValue("ItemContainerList");
   if (containers != null) {
     for (ItemContainer container : containers) {
       container.doCollection(minecart);
     }
   }
 }
 @Override
 public boolean execute(MinecartManiaMinecart minecart) {
   if (minecart.isStorageMinecart()) {
     for (AbstractItem item : items) {
       ((MinecartManiaStorageCart) minecart).setMinimumItem(item.type(), item.getAmount());
     }
     return true;
   }
   return false;
 }
  public static void doItemCompression(final MinecartManiaStorageCart minecart) {
    final HashSet<Block> blockList = minecart.getAdjacentBlocks(minecart.getRange());
    for (final Block block : blockList) {
      if (block.getTypeId() == Material.WORKBENCH.getId()) {
        final ArrayList<Sign> signList =
            SignUtils.getAdjacentMinecartManiaSignList(block.getLocation(), 2);
        for (final Sign sign : signList) {
          for (int i = 0; i < sign.getNumLines(); i++) {
            if (sign.getLine(i).toLowerCase().contains("compress items")
                || sign.getLine(i).toLowerCase().contains("compress")) {
              sign.setLine(i, "[Compress Items]");
              // TODO handling for custom recipies?
              final Material[][] compressable = {
                {
                  Material.IRON_INGOT,
                  Material.GOLD_INGOT,
                  Material.INK_SACK,
                  Material.DIAMOND,
                  Material.CLAY_BALL,
                  Material.SNOW_BALL
                },
                {
                  Material.IRON_BLOCK,
                  Material.GOLD_BLOCK,
                  Material.LAPIS_BLOCK,
                  Material.DIAMOND_BLOCK,
                  Material.CLAY,
                  Material.SNOW_BLOCK
                }
              };
              int n = 0;
              for (final Material m : compressable[0]) {
                final ItemStack masItem =
                    new ItemStack(m.getId(), (Material.INK_SACK == m) ? 4 : 0);
                final int amtPerBlock = getNumItemsInBlock(m);
                int amt = 0;
                int slot = 0;
                for (final ItemStack item : minecart.getContents()) {
                  if ((item != null)
                      && (item.getTypeId() == masItem.getTypeId())
                      && (item.getDurability() == masItem.getDurability())) {
                    amt += item.getAmount();
                    minecart.setItem(slot, null);
                  }
                  slot++;
                }
                int compressedAmt = amt / amtPerBlock;
                final int left = amt % amtPerBlock;
                while (compressedAmt > 0) {
                  minecart.addItem(compressable[1][n].getId(), Math.min(64, compressedAmt));
                  compressedAmt -= Math.min(64, compressedAmt);
                }
                if (left > 0) {
                  minecart.addItem(compressable[0][n].getId(), left);
                }

                n++;
              }
            }
          }
        }
      }
    }
  }
  public static void doCrafting(final MinecartManiaStorageCart minecart) {
    // Efficiency. Don't process overlapping tiles repeatedly, waste of time
    final int interval =
        minecart.getDataValue("Craft Interval") == null
            ? -1
            : (Integer) minecart.getDataValue("Craft Interval");
    if (interval > 0) {
      minecart.setDataValue("Craft Interval", interval - 1);
    } else {
      minecart.setDataValue("Craft Interval", minecart.getRange() / 2);
      final HashSet<Block> blockList = minecart.getAdjacentBlocks(minecart.getRange());
      for (final Block block : blockList) {
        if (block.getTypeId() == Material.WORKBENCH.getId()) {
          final ArrayList<Sign> signList =
              SignUtils.getAdjacentMinecartManiaSignList(block.getLocation(), 2);
          for (final Sign sign : signList) {
            if (sign.getLine(0).toLowerCase().contains("craft items")) {
              sign.setLine(0, "[Craft Items]");
              // For each line on the sign
              String itemListString = "";
              for (int i = 1; i < sign.getNumLines(); i++) {
                if (i > 1) {
                  itemListString += ":";
                }
                itemListString += sign.getLine(i);
              }
              for (final SpecificMaterial item :
                  ItemUtils.getItemStringListToMaterial(itemListString.split(":"))) {
                // Get the recipe, if possible
                final RecipeData recipe = RecipeManager.findRecipe(item);

                if (recipe == null) {
                  continue; // Skip if we can't find it.
                }
                if ((recipe.ingredients == null) || (recipe.ingredients.size() == 0)) {
                  continue;
                }

                boolean outOfIngredients = false;

                int loops = 0;

                final List<ItemStack> fixedIngredients = new ArrayList<ItemStack>();

                debug(
                    minecart,
                    "RECIPE: "
                        + recipe.results.toString()
                        + " (d: "
                        + recipe.results.getDurability()
                        + ")");
                // Until we're out of ingredients, or the loop has been executed 64 times.
                while (!outOfIngredients && (loops < 64)) {
                  fixedIngredients.clear();

                  loops++;
                  // Loop through the list of ingredients for this recipe
                  for (final ItemStack stack : recipe.ingredients) {
                    boolean found = false;

                    if (stack.getDurability() == (short) -1) {
                      // See what we have
                      ItemStack subitem = null;
                      for (int is = 0; is < minecart.size(); is++) {
                        final ItemStack si = minecart.getItem(is);
                        if ((si != null) && (si.getTypeId() == stack.getTypeId())) {
                          subitem = si;
                          break;
                        }
                      }
                      if (subitem == null) {
                        continue;
                      }
                      stack.setDurability(subitem.getDurability());

                      // See if we have the needed ingredient
                      final int num = minecart.amount(stack.getTypeId(), stack.getDurability());
                      if (minecart.amount(stack.getTypeId(), stack.getDurability())
                          < stack.getAmount()) {
                        continue;
                      } else {
                        debug(
                            minecart,
                            "Cart has "
                                + num
                                + " "
                                + recipe.results.toString()
                                + " (d: "
                                + recipe.results.getDurability()
                                + ")!");
                        found = true;
                        break;
                      }
                    } else {
                      if (stack.getDurability() == -1) {
                        stack.setDurability((short) 0);
                      }

                      // See if we have the needed ingredients
                      if (minecart.amount(stack.getTypeId(), stack.getDurability())
                          >= stack.getAmount()) {
                        found = true;
                      } else {
                        debug(
                            minecart,
                            "OOI: " + stack.toString() + " (d: " + stack.getDurability() + ")");
                        outOfIngredients = true;
                        break;
                      }
                    }
                    if (!found) {
                      outOfIngredients = true;
                      debug(
                          minecart,
                          "OOI: " + stack.toString() + " (d: " + stack.getDurability() + ")");
                      break;
                    } else {
                      // debug(minecart, "Ingredient found: " + stack.toString() + " (d: " +
                      // stack.getDurability() + ")");
                      fixedIngredients.add(stack);
                    }
                  }

                  if (outOfIngredients) {
                    break;
                  }

                  // Double-check
                  debug(
                      minecart,
                      "Recipe for "
                          + recipe.results.toString()
                          + " (d: "
                          + recipe.results.getDurability()
                          + ")");
                  for (final ItemStack stack : fixedIngredients) {
                    if (minecart.canRemoveItem(
                        stack.getTypeId(), stack.getAmount(), stack.getDurability())) {
                      debug(
                          minecart,
                          " + " + stack.toString() + " (d: " + stack.getDurability() + ")");
                    } else {
                      debug(
                          minecart,
                          "OOI: " + stack.toString() + " (d: " + stack.getDurability() + ")");
                      outOfIngredients = true;
                      break;
                    }
                  }

                  if (outOfIngredients) {
                    break;
                  }

                  if (!minecart.canAddItem(recipe.results)) {
                    debug(minecart, "CAI: " + recipe.results.toString());
                    outOfIngredients = true;
                    break;
                  }

                  // Loop through again to actually remove the items
                  for (final ItemStack stack : fixedIngredients) {
                    debug(
                        minecart,
                        "[Craft Items] Removed "
                            + stack.toString()
                            + " (d: "
                            + stack.getDurability()
                            + ") from minecart!");
                    minecart.removeItem(
                        stack.getTypeId(), stack.getAmount(), stack.getDurability());
                  }
                  // Take it from the cart
                  minecart.addItem(recipe.results);
                  debug(
                      minecart,
                      "[Craft Items] Added " + recipe.results.toString() + " to minecart!");
                }
              }
            }
          }
        }
      }
    }
  }
 public static void debug(final MinecartManiaStorageCart minecart, final String msg) {
   if (minecart.getDataValue("MMDebug") != null) {
     System.out.println(msg);
   }
 }