public static boolean doCollectParallel(final MinecartManiaMinecart minecart) {
   final ArrayList<Block> blockList = minecart.getParallelBlocks();
   for (final Block block : blockList) {
     if (block.getState() instanceof Chest) {
       final MinecartManiaChest chest =
           MinecartManiaWorld.getMinecartManiaChest((Chest) block.getState());
       final ArrayList<Sign> signList =
           SignUtils.getAdjacentMinecartManiaSignList(chest.getLocation(), 1);
       for (final Sign sign : signList) {
         for (int i = 0; i < sign.getNumLines(); i++) {
           if (sign.getLine(i).toLowerCase().contains("parallel")) {
             sign.setLine(i, "[Parallel]");
             if (!minecart.isMovingAway(block.getLocation())) {
               if (chest.addItem(minecart.getType().getId())) {
                 minecart.kill(false);
                 return true;
               }
             }
           }
         }
       }
     }
   }
   return false;
 }
 public static boolean isNoCollection(final MinecartManiaChest chest) {
   final ArrayList<Sign> signList =
       SignUtils.getAdjacentMinecartManiaSignList(chest.getLocation(), 2);
   for (final Sign sign : signList) {
     for (int i = 0; i < sign.getNumLines(); i++) {
       if (sign.getLine(i).toLowerCase().contains("no collection")) {
         sign.setLine(i, "[No Collection]");
         return true;
       }
     }
   }
   return false;
 }
  // NOTE: Bukkit getRelative() still seems to follow old directionality. As a quick fix,
  //       all calls to getAdjacentTrack() have been changed into "wrong" looking ones!
  public static Location getSpawnLocationSignOverride(final MinecartManiaChest chest) {
    final ArrayList<Sign> signList =
        SignUtils.getAdjacentMinecartManiaSignList(chest.getLocation(), 2);
    final Location spawn = chest.getLocation();
    Location result = null;
    final Block neighbor =
        chest.getNeighborChest() != null ? chest.getNeighborChest().getLocation().getBlock() : null;

    for (final Sign sign : signList) {
      for (int i = 0; i < sign.getNumLines(); i++) {
        if (sign.getLine(i).toLowerCase().contains("spawn north")) {
          sign.setLine(i, "[Spawn North]");
          result = getAdjacentTrack(spawn.getBlock(), BlockFace.EAST);
          if ((result == null) && (neighbor != null))
            return getAdjacentTrack(neighbor, BlockFace.EAST);
          else return result;
        }
        if (sign.getLine(i).toLowerCase().contains("spawn east")) {
          sign.setLine(i, "[Spawn East]");
          result = getAdjacentTrack(spawn.getBlock(), BlockFace.SOUTH);
          if ((result == null) && (neighbor != null))
            return getAdjacentTrack(neighbor, BlockFace.SOUTH);
          else return result;
        }
        if (sign.getLine(i).toLowerCase().contains("spawn south")) {
          sign.setLine(i, "[Spawn South]");
          result = getAdjacentTrack(spawn.getBlock(), BlockFace.WEST);
          if ((result == null) && (neighbor != null))
            return getAdjacentTrack(neighbor, BlockFace.WEST);
          else return result;
        }
        if (sign.getLine(i).toLowerCase().contains("spawn west")) {
          sign.setLine(i, "[Spawn West]");
          result = getAdjacentTrack(spawn.getBlock(), BlockFace.NORTH);
          if ((result == null) && (neighbor != null))
            return getAdjacentTrack(neighbor, BlockFace.NORTH);
          else return result;
        }
      }
    }

    return null;
  }
  public static Material getMinecartType(final MinecartManiaChest chest) {
    final ArrayList<com.afforess.minecartmaniacore.signs.Sign> signList =
        SignUtils.getAdjacentMinecartManiaSignList(chest.getLocation(), 2);
    for (final com.afforess.minecartmaniacore.signs.Sign sign : signList) {
      if (sign instanceof MinecartTypeSign) {
        final MinecartTypeSign type = (MinecartTypeSign) sign;
        if (type.canDispenseMinecartType(Material.MINECART)) {
          if (chest.contains(Material.MINECART)) return Material.MINECART;
        }
        if (type.canDispenseMinecartType(Material.POWERED_MINECART)) {
          if (chest.contains(Material.POWERED_MINECART)) return Material.POWERED_MINECART;
        }
        if (type.canDispenseMinecartType(Material.STORAGE_MINECART)) {
          if (chest.contains(Material.STORAGE_MINECART)) return Material.STORAGE_MINECART;
        }
      }
    }

    // Returns standard minecart by default
    return Material.MINECART;
  }
  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!");
                }
              }
            }
          }
        }
      }
    }
  }