/** Copyright (C) <2015> <coolAlias> This file is part of coolAlias' Zelda Sword Skills Minecraft Mod; as such, you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ package zeldaswordskills.util; import java.util.Iterator; import net.minecraft.item.ItemStack; import net.minecraft.village.MerchantRecipe; import net.minecraft.village.MerchantRecipeList; /** * * Helper methods for interacting with MerchantRecipeLists and MerchantRecipes * */ public class MerchantRecipeHelper { /** * Returns true if a recipe (trade) with the exact same stacks already exists in the merchant's list * This method uses vanilla ItemStack.areItemStacksEqual, so it should be NBT sensitive as well * @return always returns true if the recipe is null */ public static boolean doesListContain(MerchantRecipeList trades, MerchantRecipe recipe) { if (recipe == null) { return true; } for (int i = 0; i < trades.size(); ++i) { if (areTradesIdentical(recipe, (MerchantRecipe) trades.get(i))) { return true; } } return false; } /** * Returns true if a MerchantRecipe (trade) containing the same items already * exists in the merchant's list; not stack-size or NBT sensitive * @return returns false if the trade is null or no similar trade was found */ public static boolean hasSimilarTrade(MerchantRecipeList trades, MerchantRecipe trade) { if (trade == null || trades == null) { return false; } for (int i = 0; i < trades.size(); ++i) { MerchantRecipe trade1 = (MerchantRecipe) trades.get(i); if (haveSameTradeItems(trade, trade1)) { return true; } } return false; } /** * Adds a trade to the merchant's list only if a similar trade does not already exist * @return True if the trade was added, false if the trade was already present */ public static boolean addUniqueTrade(MerchantRecipeList trades, MerchantRecipe trade) { if (!doesListContain(trades, trade)) { trades.add(trade); return true; } return false; } /** * Shortcut method to attempt adding a trade without replacing a currently existing trade * @return returns true if the new trade was added */ public static boolean addToListWithCheck(MerchantRecipeList trades, MerchantRecipe trade) { return addToListWithCheck(trades, trade, false); } /** * Adds the trade to the list if and only if a similar trade (i.e. same Items but different * stack sizes) doesn't already exist, or if 'replaceExistingTrade' is true. * @return returns true if the new trade was added or replaced a current trade */ public static boolean addToListWithCheck(MerchantRecipeList trades, MerchantRecipe trade, boolean replaceExistingTrade) { for (int i = 0; i < trades.size(); ++i) { MerchantRecipe merchantrecipe1 = (MerchantRecipe) trades.get(i); if (haveSameTradeItems(trade, merchantrecipe1)) { if (replaceExistingTrade) { trades.set(i, trade); return true; } return false; } } trades.add(trade); return true; } /** * Removes matching trades from the recipe list * @param exactMatch true to match stack sizes and NBTTagCompounds * @param removeAll true to remove all matching trades, or false to remove only one * @return true if trade was removed */ public static boolean removeTrade(MerchantRecipeList trades, MerchantRecipe trade, boolean exactMatch, boolean removeAll) { boolean found = false; Iterator<MerchantRecipe> iterator = trades.iterator(); while (iterator.hasNext()) { MerchantRecipe recipe = iterator.next(); if (exactMatch ? areTradesIdentical(trade, recipe) : haveSameTradeItems(trade, recipe)) { iterator.remove(); if (!removeAll) { return true; } found = true; } } return found; } /** * Returns true if all the items (to buy and sell) have matching item IDs and metadata * Does not care about stack size or NBT tags. */ public static boolean haveSameTradeItems(MerchantRecipe a, MerchantRecipe b) { ItemStack item1a = a.getItemToBuy(); ItemStack item1b = b.getItemToBuy(); ItemStack item2a = a.getItemToSell(); ItemStack item2b = b.getItemToSell(); ItemStack item3a = a.getSecondItemToBuy(); ItemStack item3b = b.getSecondItemToBuy(); if (item1a != null && item1b != null && item1a.getItem() == item1b.getItem() && item1a.getItemDamage() == item1b.getItemDamage()) { if (item2a != null && item2b != null && item2a.getItem() == item2b.getItem() && item2a.getItemDamage() == item2b.getItemDamage()) { return (item3a == null && item3b == null) || (item3a != null && item3b != null && item3a.getItem() == item3b.getItem() && item3a.getItemDamage() == item3b.getItemDamage()); } } return false; } /** * Returns true if the two trades match identically, including stack sizes and NBT tag compounds for each item. * Neither parameter should be null. */ public static boolean areTradesIdentical(MerchantRecipe a, MerchantRecipe b) { if (ItemStack.areItemStacksEqual(a.getItemToBuy(), b.getItemToBuy())) { if (ItemStack.areItemStacksEqual(a.getSecondItemToBuy(), b.getSecondItemToBuy())) { if (ItemStack.areItemStacksEqual(a.getItemToSell(), b.getItemToSell())) { return true; } } } return false; } }