| package mekanism.common.recipe; |
| |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.Map; |
| |
| import mekanism.api.energy.IEnergizedItem; |
| import mekanism.api.gas.GasStack; |
| import mekanism.api.gas.IGasItem; |
| import mekanism.common.Upgrade; |
| import mekanism.common.base.IEnergyCube; |
| import mekanism.common.base.IFactory; |
| import mekanism.common.block.BlockMachine.MachineType; |
| import mekanism.common.item.ItemBlockBasic; |
| import net.minecraft.block.Block; |
| import net.minecraft.inventory.InventoryCrafting; |
| import net.minecraft.item.Item; |
| import net.minecraft.item.ItemStack; |
| import net.minecraft.item.crafting.IRecipe; |
| import net.minecraft.nbt.NBTTagCompound; |
| import net.minecraft.world.World; |
| import net.minecraftforge.oredict.OreDictionary; |
| |
| /** |
| * Code originally from Eloraam and her work on the Ore Dictionary. Cleaned up and modified to work well with energized items. |
| * @author Eloraam, aidancbrady |
| * |
| */ |
| public class MekanismRecipe implements IRecipe |
| { |
| private static final int MAX_CRAFT_GRID_WIDTH = 3; |
| private static final int MAX_CRAFT_GRID_HEIGHT = 3; |
| |
| private ItemStack output = null; |
| private Object[] input = null; |
| |
| public int width = 0; |
| public int height = 0; |
| |
| private boolean mirrored = true; |
| |
| public MekanismRecipe(ItemStack result, Object... recipe) |
| { |
| output = result.copy(); |
| |
| String shape = ""; |
| int idx = 0; |
| |
| if(recipe[idx] instanceof Boolean) |
| { |
| mirrored = (Boolean)recipe[idx]; |
| |
| if(recipe[idx+1] instanceof Object[]) |
| { |
| recipe = (Object[])recipe[idx+1]; |
| } |
| else { |
| idx = 1; |
| } |
| } |
| |
| if(recipe[idx] instanceof String[]) |
| { |
| String[] parts = ((String[])recipe[idx++]); |
| |
| for(String s : parts) |
| { |
| width = s.length(); |
| shape += s; |
| } |
| |
| height = parts.length; |
| } |
| else { |
| while(recipe[idx] instanceof String) |
| { |
| String s = (String)recipe[idx++]; |
| shape += s; |
| width = s.length(); |
| height++; |
| } |
| } |
| |
| if(width * height != shape.length()) |
| { |
| String ret = "Invalid shaped ore recipe: "; |
| |
| for(Object tmp : recipe) |
| { |
| ret += tmp + ", "; |
| } |
| |
| ret += output; |
| |
| throw new RuntimeException(ret); |
| } |
| |
| HashMap<Character, Object> itemMap = new HashMap<Character, Object>(); |
| |
| for(; idx < recipe.length; idx += 2) |
| { |
| Character chr = (Character)recipe[idx]; |
| Object in = recipe[idx + 1]; |
| |
| if(in instanceof ItemStack) |
| { |
| itemMap.put(chr, ((ItemStack)in).copy()); |
| } |
| else if(in instanceof Item) |
| { |
| itemMap.put(chr, new ItemStack((Item)in)); |
| } |
| else if(in instanceof Block) |
| { |
| itemMap.put(chr, new ItemStack((Block)in, 1, OreDictionary.WILDCARD_VALUE)); |
| } |
| else if(in instanceof String) |
| { |
| itemMap.put(chr, OreDictionary.getOres((String)in)); |
| } |
| else { |
| String ret = "Invalid shaped ore recipe: "; |
| |
| for(Object tmp : recipe) |
| { |
| ret += tmp + ", "; |
| } |
| |
| ret += output; |
| throw new RuntimeException(ret); |
| } |
| } |
| |
| input = new Object[width * height]; |
| int x = 0; |
| |
| for(char chr : shape.toCharArray()) |
| { |
| input[x++] = itemMap.get(chr); |
| } |
| } |
| |
| @Override |
| public ItemStack getCraftingResult(InventoryCrafting inv) |
| { |
| ItemStack toReturn = output.copy(); |
| |
| if(toReturn.getItem() instanceof IEnergizedItem) |
| { |
| double energyFound = 0; |
| |
| for(int i = 0; i < 9; i++) |
| { |
| ItemStack itemstack = inv.getStackInSlot(i); |
| |
| if(itemstack != null && itemstack.getItem() instanceof IEnergizedItem) |
| { |
| energyFound += ((IEnergizedItem)itemstack.getItem()).getEnergy(itemstack); |
| } |
| } |
| |
| ((IEnergizedItem)toReturn.getItem()).setEnergy(toReturn, Math.min(((IEnergizedItem)toReturn.getItem()).getMaxEnergy(toReturn), energyFound)); |
| } |
| |
| if(toReturn.getItem() instanceof IGasItem) |
| { |
| GasStack gasFound = null; |
| |
| for(int i = 0; i < 9; i++) |
| { |
| ItemStack itemstack = inv.getStackInSlot(i); |
| |
| if(itemstack != null && itemstack.getItem() instanceof IGasItem) |
| { |
| GasStack stored = ((IGasItem)itemstack.getItem()).getGas(itemstack); |
| |
| if(stored != null) |
| { |
| if(!((IGasItem)toReturn.getItem()).canReceiveGas(toReturn, stored.getGas())) |
| { |
| return null; |
| } |
| |
| if(gasFound == null) |
| { |
| gasFound = stored; |
| } |
| else { |
| if(gasFound.getGas() != stored.getGas()) |
| { |
| return null; |
| } |
| |
| gasFound.amount += stored.amount; |
| } |
| } |
| } |
| } |
| |
| if(gasFound != null) |
| { |
| gasFound.amount = Math.min(((IGasItem)toReturn.getItem()).getMaxGas(toReturn), gasFound.amount); |
| ((IGasItem)toReturn.getItem()).setGas(toReturn, gasFound); |
| } |
| } |
| |
| if(MachineType.get(toReturn).supportsUpgrades) |
| { |
| Map<Upgrade, Integer> upgrades = new HashMap<Upgrade, Integer>(); |
| |
| for(int i = 0; i < 9; i++) |
| { |
| ItemStack itemstack = inv.getStackInSlot(i); |
| |
| if(itemstack != null && MachineType.get(itemstack).supportsUpgrades) |
| { |
| Map<Upgrade, Integer> stackMap = Upgrade.buildMap(itemstack.stackTagCompound); |
| |
| for(Map.Entry<Upgrade, Integer> entry : stackMap.entrySet()) |
| { |
| upgrades.put(entry.getKey(), Math.min(entry.getKey().getMax(), upgrades.get(entry.getKey()) + entry.getValue())); |
| } |
| } |
| } |
| |
| if(toReturn.stackTagCompound == null) |
| { |
| toReturn.setTagCompound(new NBTTagCompound()); |
| } |
| |
| Upgrade.saveMap(upgrades, toReturn.stackTagCompound); |
| } |
| |
| return toReturn; |
| } |
| |
| @Override |
| public int getRecipeSize() |
| { |
| return input.length; |
| } |
| |
| @Override |
| public ItemStack getRecipeOutput() |
| { |
| return output; |
| } |
| |
| @Override |
| public boolean matches(InventoryCrafting inv, World world) |
| { |
| for(int x = 0; x <= MAX_CRAFT_GRID_WIDTH - width; x++) |
| { |
| for(int y = 0; y <= MAX_CRAFT_GRID_HEIGHT - height; ++y) |
| { |
| if(checkMatch(inv, x, y, true)) |
| { |
| return true; |
| } |
| |
| if(mirrored && checkMatch(inv, x, y, false)) |
| { |
| return true; |
| } |
| } |
| } |
| |
| return false; |
| } |
| |
| private boolean checkMatch(InventoryCrafting inv, int startX, int startY, boolean mirror) |
| { |
| for(int x = 0; x < MAX_CRAFT_GRID_WIDTH; x++) |
| { |
| for(int y = 0; y < MAX_CRAFT_GRID_HEIGHT; y++) |
| { |
| int subX = x - startX; |
| int subY = y - startY; |
| Object target = null; |
| |
| if(subX >= 0 && subY >= 0 && subX < width && subY < height) |
| { |
| if(mirror) |
| { |
| target = input[width - subX - 1 + subY * width]; |
| } |
| else { |
| target = input[subX + subY * width]; |
| } |
| } |
| |
| ItemStack slot = inv.getStackInRowAndColumn(x, y); |
| |
| if(target instanceof ItemStack) |
| { |
| if(!checkItemEquals((ItemStack)target, slot)) |
| { |
| return false; |
| } |
| } |
| else if(target instanceof ArrayList) |
| { |
| boolean matched = false; |
| |
| for(ItemStack item : (ArrayList<ItemStack>)target) |
| { |
| matched = matched || checkItemEquals(item, slot); |
| } |
| |
| if(!matched) |
| { |
| return false; |
| } |
| } |
| else if(target == null && slot != null) |
| { |
| return false; |
| } |
| } |
| } |
| |
| return true; |
| } |
| |
| private boolean checkItemEquals(ItemStack target, ItemStack input) |
| { |
| if(input == null && target != null || input != null && target == null) |
| { |
| return false; |
| } |
| else if(input == null && target == null) |
| { |
| return true; |
| } |
| |
| if(target.getItem() != input.getItem()) |
| { |
| return false; |
| } |
| |
| if(!(target.getItem() instanceof IEnergizedItem) && !(input.getItem() instanceof IEnergizedItem) && !(target.getItem() instanceof IGasItem) && !(input.getItem() instanceof IGasItem)) |
| { |
| if(target.getItemDamage() != input.getItemDamage() && target.getItemDamage() != OreDictionary.WILDCARD_VALUE) |
| { |
| return false; |
| } |
| } |
| else { |
| if(target.getItem() instanceof IEnergizedItem && input.getItem() instanceof IEnergizedItem) |
| { |
| if(((IEnergizedItem)target.getItem()).isMetadataSpecific(target) && ((IEnergizedItem)input.getItem()).isMetadataSpecific(input)) |
| { |
| if(target.getItemDamage() != input.getItemDamage() && target.getItemDamage() != OreDictionary.WILDCARD_VALUE) |
| { |
| return false; |
| } |
| } |
| } |
| |
| if(target.getItem() instanceof IGasItem && input.getItem() instanceof IGasItem) |
| { |
| if(((IGasItem)target.getItem()).isMetadataSpecific(target) && ((IGasItem)input.getItem()).isMetadataSpecific(input)) |
| { |
| if(target.getItemDamage() != input.getItemDamage() && target.getItemDamage() != OreDictionary.WILDCARD_VALUE) |
| { |
| return false; |
| } |
| } |
| } |
| |
| if(target.getItem() instanceof IEnergyCube && input.getItem() instanceof IEnergyCube) |
| { |
| if(((IEnergyCube)target.getItem()).getEnergyCubeTier(target) != ((IEnergyCube)input.getItem()).getEnergyCubeTier(input)) |
| { |
| return false; |
| } |
| } |
| else if(target.getItem() instanceof ItemBlockBasic && input.getItem() instanceof ItemBlockBasic) |
| { |
| if(((ItemBlockBasic)target.getItem()).getTier(target) != ((ItemBlockBasic)input.getItem()).getTier(input)) |
| { |
| return false; |
| } |
| } |
| else if(target.getItem() instanceof IFactory && input.getItem() instanceof IFactory) |
| { |
| if(isFactory(target) && isFactory(input)) |
| { |
| if(((IFactory)target.getItem()).getRecipeType(target) != ((IFactory)input.getItem()).getRecipeType(input)) |
| { |
| return false; |
| } |
| } |
| } |
| } |
| |
| return true; |
| } |
| |
| private static boolean isFactory(ItemStack stack) |
| { |
| return MachineType.get(stack) == MachineType.BASIC_FACTORY || MachineType.get(stack) == MachineType.ADVANCED_FACTORY || MachineType.get(stack) == MachineType.ELITE_FACTORY; |
| } |
| |
| public MekanismRecipe setMirrored(boolean mirror) |
| { |
| mirrored = mirror; |
| return this; |
| } |
| |
| public Object[] getInput() |
| { |
| return input; |
| } |
| } |