package gr8pefish.ironbackpacks.crafting; import gr8pefish.ironbackpacks.api.items.backpacks.interfaces.IUpgradableBackpack; import gr8pefish.ironbackpacks.api.items.upgrades.ItemIConflictingUpgrade; import gr8pefish.ironbackpacks.api.recipes.IAddUpgradeRecipe; import gr8pefish.ironbackpacks.api.register.ItemIUpgradeRegistry; import gr8pefish.ironbackpacks.config.ConfigHandler; import gr8pefish.ironbackpacks.items.backpacks.ItemBackpack; import gr8pefish.ironbackpacks.items.upgrades.ItemUpgrade; import gr8pefish.ironbackpacks.items.upgrades.UpgradeMethods; import gr8pefish.ironbackpacks.registry.ItemRegistry; import gr8pefish.ironbackpacks.util.IronBackpacksConstants; import gr8pefish.ironbackpacks.util.helpers.IronBackpacksHelper; import net.minecraft.inventory.InventoryCrafting; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagIntArray; import net.minecraft.nbt.NBTTagList; import net.minecraftforge.oredict.ShapelessOreRecipe; import java.util.ArrayList; import java.util.List; /** * Deals with the cases when a backpack is shapelessly crafted with an upgrade. */ public class BackpackAddUpgradeRecipe extends ShapelessOreRecipe implements IAddUpgradeRecipe{ private final ItemStack recipeOutput; //The outputted items after recipes public BackpackAddUpgradeRecipe(ItemStack recipeOutput, Object... items){ super(recipeOutput, items); this.recipeOutput = recipeOutput; } /** * Crafts the backpack with the upgrade, with some special cases recognized. * First it checks if the backpack has enough upgrade points available to apply said upgrade to the backpack. * If it has enough points available it progresses, otherwise it returns null; * * Then it checks for special cases, listed below: * You can't have more than the config amount of 'additional upgrade points' upgrades applied. * You can't have conflicting upgrades (as defined by each IConflictingUpgrade). * You can only have a certain amount of alternate gui upgrades. Currently 'hardcoded' as 4, see IronBackpacksConstants.Upgrades.ALT_GUI_UPGRADES_ALLOWED * * @param inventoryCrafting - the inventory recipes to check * @return - the resulting itemstack */ @Override public ItemStack getCraftingResult(InventoryCrafting inventoryCrafting) { ItemStack backpack = getFirstUpgradableBackpack(inventoryCrafting); //get the upgradable backpack in the recipes grid if (backpack == null) return null; //if no valid backpack return nothing ItemStack result = backpack.copy(); //the resulting backpack, copied so it's data can be more easily manipulated ArrayList<ItemStack> upgrades = IronBackpacksHelper.getUpgradesAppliedFromNBT(result); //get the upgrades int totalUpgradePoints = IronBackpacksHelper.getTotalUpgradePointsFromNBT(result); //get the total upgrade points available to the backpack ItemStack upgradeToApply = getFirstUpgrade(inventoryCrafting); //get the upgrade the player is attempting to apply to the backpack //save all the items from the old pack NBTTagCompound nbtTagCompound = result.getTagCompound(); if (nbtTagCompound == null){ nbtTagCompound = new NBTTagCompound(); nbtTagCompound.setTag(IronBackpacksConstants.NBTKeys.ITEMS, new NBTTagList()); result.setTagCompound(nbtTagCompound); } boolean upgradeFound = false; //too determine if you need to return a new backpack in the output slot NBTTagList tagList = new NBTTagList(); //the upgrade data base tag if (totalUpgradePoints != 0 && upgradeToApply != null) { //if have more than zero upgrade slots if (upgrades.size() == 0){ //if no upgrades applied if (ItemUpgrade.areUpgradesEqual(upgradeToApply, ItemRegistry.additionalUpgradePointsUpgrade)){ //if the upgrade is an additional upgrade points upgrade upgradeFound = applyAdditional(nbtTagCompound, result); //if you can apply more upgrade points, do it } else { //some other upgrade (i.e. not additional upgrade points) if (IronBackpacksHelper.getUpgradePointsUsed(upgrades) + ItemUpgrade.getUpgradeCost(upgradeToApply) <= totalUpgradePoints) { //if you have enough upgrade points to apply it if (ItemIUpgradeRegistry.isInstanceOfIConfigurableUpgrade(upgradeToApply)) //if it is an alt gui upgrade nbtTagCompound.setTag(IronBackpacksConstants.NBTKeys.ADDED_ALT_GUI, upgradeToApply.writeToNBT(new NBTTagCompound())); //make sure to update so the alt gui can change when it is opened tagList.appendTag(upgradeToApply.writeToNBT(new NBTTagCompound())); //save the new upgrade upgradeFound = true; //you applied an upgrade, congratulations } } } else { //upgrades have been applied if (ItemUpgrade.areUpgradesEqual(upgradeToApply, ItemRegistry.additionalUpgradePointsUpgrade)) { //if the upgrade is an additional upgrade points upgrade upgradeFound = applyAdditional(nbtTagCompound, result); //if you can apply more upgrade points, do it } for (ItemStack upgrade : upgrades) { //for each upgrade in possible upgrades tagList.appendTag(upgrade.writeToNBT(new NBTTagCompound())); //save old contents to new tag (transfer over the data, essentially) } if (!upgradeFound && !(ItemUpgrade.areUpgradesEqual(upgradeToApply, ItemRegistry.additionalUpgradePointsUpgrade))){ //if not already applied if (canApplyUpgrade(upgrades, totalUpgradePoints, upgradeToApply)){ //if you can apply the upgrade (this checks special conditions (i.e. IConflictingUpgrades) too) if (ItemIUpgradeRegistry.isInstanceOfIConfigurableUpgrade(upgradeToApply)) //if it is an alt gui upgrade nbtTagCompound.setTag(IronBackpacksConstants.NBTKeys.ADDED_ALT_GUI, upgradeToApply.writeToNBT(new NBTTagCompound())); //make sure to update so the alt gui can change when it is opened tagList.appendTag(upgradeToApply.writeToNBT(new NBTTagCompound())); //save the new upgrade upgradeFound = true; //you applied an upgrade, congratulations } } } } else if (upgradeToApply != null && ItemUpgrade.areUpgradesEqual(upgradeToApply, ItemRegistry.additionalUpgradePointsUpgrade)){ //if no upgrade points you could apply to get more upgrade points (corner case) upgradeFound = applyAdditional(nbtTagCompound, result); //if you can apply more upgrade points, do it } nbtTagCompound.setTag(IronBackpacksConstants.NBTKeys.UPGRADES, tagList); //set the tag with all the upgrade that were just updated if (upgradeFound) { //if you applied an upgrade return result; //return the new backpack } else { //otherwise return null; //return nothing } } @Override public ItemStack getRecipeOutput() { return recipeOutput; } //=============================================================================Helper Methods==================================================================== /** * Helper method for getting the first backpack in the recipes grid (which will be the one used) * @param inventoryCrafting - the inventory to search * @return - the backpack to be crafted */ private static ItemStack getFirstUpgradableBackpack(InventoryCrafting inventoryCrafting) { for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { ItemStack itemstack = inventoryCrafting.getStackInRowAndColumn(j, i); if (itemstack != null && (itemstack.getItem() instanceof IUpgradableBackpack)) { return itemstack; } } } return null; } /** * Helper method for getting the first upgrade in the recipes grid (which will be the one used) * @param inventoryCrafting - the inventory to search * @return - the upgrade to be used */ private static ItemStack getFirstUpgrade(InventoryCrafting inventoryCrafting){ for (int i = 0; i < 3; ++i) { for (int j = 0; j < 3; ++j) { ItemStack itemstack = inventoryCrafting.getStackInRowAndColumn(j, i); if (itemstack != null && itemstack.getItem() != null) { if (itemstack.getItem() instanceof ItemUpgrade) { //hardcoded for ItemIUpgrade if (ItemIUpgradeRegistry.isInstanceOfAnyUpgrade(itemstack)) { //any upgrade is fine here ItemStack returnStack = itemstack.copy(); //copy stack returnStack.stackSize = 1; //only apply 1 upgrade (stack size of 1) return returnStack; } } } } } return null; } /** * Checks the special conditions to see if the upgrade can be applied. Also checks if the backpack has sufficient available upgrade points to apply the upgrade. * @param upgrades - the upgrades already on the backpack * @param totalUpgradePoints - the total upgrade points on the backpack * @param upgradeToApply - the upgradeToApply as an itemstack * @return - true if it can be applied, false otherwise */ private boolean canApplyUpgrade(ArrayList<ItemStack> upgrades, int totalUpgradePoints, ItemStack upgradeToApply){ if (ItemIUpgradeRegistry.isInstanceOfIConflictingUpgrade(upgradeToApply) || ItemIUpgradeRegistry.isInstanceOfIConfigurableUpgrade(upgradeToApply)){ for (ItemStack upgrade : upgrades) { //check for duplicate if (UpgradeMethods.areUpgradesFunctionallyEquivalent(upgrade, upgradeToApply)) //if duplicate upgrade return false; //can't apply } if (ItemIUpgradeRegistry.isInstanceOfIConflictingUpgrade(upgradeToApply)){ //conflicting if (hasConflictingUpgradeInUpgrades(upgradeToApply, upgrades)){ //if has the conflicting upgrade return false; //can't apply conflicting } else { //no conflicting one tried to be applied return IronBackpacksHelper.getUpgradePointsUsed(upgrades) + ItemUpgrade.getUpgradeCost(upgradeToApply) <= totalUpgradePoints; //if you have the upgrade points } } else{ //alt gui upgrade if (UpgradeMethods.getAltGuiUpgradesApplied(upgrades) + 1 <= IronBackpacksConstants.Upgrades.ALT_GUI_UPGRADES_ALLOWED){ //if you can fit the alt gui return IronBackpacksHelper.getUpgradePointsUsed(upgrades) + ItemUpgrade.getUpgradeCost(upgradeToApply) <= totalUpgradePoints; //if you have the upgrade points } else { //you can't fit another alternate gui upgrade return false; //can't apply it } } } else { //normal upgrade for (ItemStack upgrade : upgrades) { //check for duplicate if (UpgradeMethods.areUpgradesFunctionallyEquivalent(upgrade, upgradeToApply)) //if duplicate upgrade return false; //can't apply } return IronBackpacksHelper.getUpgradePointsUsed(upgrades) + ItemUpgrade.getUpgradeCost(upgradeToApply) <= totalUpgradePoints; //if you have the upgrade points } } /** * Check if the backpack's upgrades contain a conflicting upgrade (relative to the upgradeToApply itemStack). * @param upgradeToApply - the upgrade that is attempted to be applied * @param upgrades - the current upgrades on the pack * @return - true if it has a conflicting upgrade, false otherwise */ private boolean hasConflictingUpgradeInUpgrades(ItemStack upgradeToApply, ArrayList<ItemStack> upgrades) { List<ItemIConflictingUpgrade> conflictingUpgrades = ItemIUpgradeRegistry.getItemIConflictingUpgrade(upgradeToApply).getConflictingUpgrades(upgradeToApply); for (ItemStack stack : upgrades){ //for every upgrade if (ItemIUpgradeRegistry.isInstanceOfIConflictingUpgrade(stack)){ //if it is an instance of a conflicting upgrade if (conflictingUpgrades.contains(ItemIUpgradeRegistry.getItemIConflictingUpgrade(stack))){ //if it specifically conflicts with this upgrade applied return true; } } } return false; } /** * Applies the upgrade to the backpack by adding it's NBT data. * @param nbtTagCompound - the tag compound of the resulting itemstack * @param backpack - the backpack in the recipes grid * @return - true if it can be applied, false otherwise */ //TODO: Clean up private boolean applyAdditional(NBTTagCompound nbtTagCompound, ItemStack backpack){ ItemBackpack backpackBase = (ItemBackpack) backpack.getItem(); if (backpackBase == null) return false; if (nbtTagCompound.hasKey(IronBackpacksConstants.NBTKeys.ADDITIONAL_POINTS)){ int[] oldValuesArray = nbtTagCompound.getIntArray(IronBackpacksConstants.NBTKeys.ADDITIONAL_POINTS); // if (oldValuesArray[1] < ConfigHandler.additionalUpgradePointsLimit + backpackBase.getGuiId(backpack)){ if (oldValuesArray[1] < ((IUpgradableBackpack)backpack.getItem()).getAdditionalUpgradePoints(backpack)){ nbtTagCompound.setTag(IronBackpacksConstants.NBTKeys.ADDITIONAL_POINTS, new NBTTagIntArray(new int[]{ConfigHandler.additionalUpgradePointsIncrease + oldValuesArray[0], ++oldValuesArray[1]})); //[pointsAdded, upgradesApplied] return true; } } else { // if (ConfigHandler.additionalUpgradePointsLimit + backpackBase.getGuiId(backpack) > 0) { if (((IUpgradableBackpack)backpack.getItem()).getAdditionalUpgradePoints(backpack) > 0) { //if upgrade points possible greater than 0, apply it nbtTagCompound.setTag(IronBackpacksConstants.NBTKeys.ADDITIONAL_POINTS, new NBTTagIntArray(new int[]{ConfigHandler.additionalUpgradePointsIncrease, 1})); //[pointsAdded, upgradesApplied] return true; } } return false; } }