001package net.minecraftforge.oredict;
002
003import java.util.ArrayList;
004import java.util.Iterator;
005import java.util.Map;
006import java.util.Map.Entry;
007import java.util.List;
008
009import net.minecraft.block.Block;
010import net.minecraft.item.crafting.CraftingManager;
011import net.minecraft.item.crafting.IRecipe;
012import net.minecraft.inventory.InventoryCrafting;
013import net.minecraft.item.Item;
014import net.minecraft.item.ItemStack;
015import net.minecraft.item.crafting.ShapelessRecipes;
016import net.minecraft.world.World;
017
018public class ShapelessOreRecipe implements IRecipe 
019{
020    private ItemStack output = null;
021    private ArrayList input = new ArrayList();    
022
023    public ShapelessOreRecipe(Block result, Object... recipe){ this(new ItemStack(result), recipe); }
024    public ShapelessOreRecipe(Item  result, Object... recipe){ this(new ItemStack(result), recipe); }
025    
026    public ShapelessOreRecipe(ItemStack result, Object... recipe)
027    {
028        output = result.copy();
029        for (Object in : recipe)
030        {
031            if (in instanceof ItemStack)
032            {
033                input.add(((ItemStack)in).copy());
034            }
035            else if (in instanceof Item)
036            {
037                input.add(new ItemStack((Item)in));
038            }
039            else if (in instanceof Block)
040            {
041                input.add(new ItemStack((Block)in));
042            }
043            else if (in instanceof String)
044            {
045                input.add(OreDictionary.getOres((String)in));
046            }
047            else
048            {
049                String ret = "Invalid shapeless ore recipe: ";
050                for (Object tmp :  recipe)
051                {
052                    ret += tmp + ", ";
053                }
054                ret += output;
055                throw new RuntimeException(ret);
056            }
057        }
058    }
059
060    ShapelessOreRecipe(ShapelessRecipes recipe, Map<ItemStack, String> replacements)
061    {
062        output = recipe.getRecipeOutput();
063
064        for(ItemStack ingred : ((List<ItemStack>)recipe.recipeItems))
065        {
066            Object finalObj = ingred;
067            for(Entry<ItemStack, String> replace : replacements.entrySet())
068            {
069                if(OreDictionary.itemMatches(replace.getKey(), ingred, false))
070                {
071                    finalObj = OreDictionary.getOres(replace.getValue());
072                    break;
073                }
074            }
075            input.add(finalObj);
076        }
077    }
078
079    @Override
080    public int getRecipeSize(){ return input.size(); }
081
082    @Override
083    public ItemStack getRecipeOutput(){ return output; }
084    
085    @Override
086    public ItemStack getCraftingResult(InventoryCrafting var1){ return output.copy(); }
087    
088    @Override
089    public boolean matches(InventoryCrafting var1, World world) 
090    {
091        ArrayList required = new ArrayList(input);
092
093        for (int x = 0; x < var1.getSizeInventory(); x++)
094        {
095            ItemStack slot = var1.getStackInSlot(x);
096
097            if (slot != null)
098            {
099                boolean inRecipe = false;
100                Iterator req = required.iterator();
101
102                while (req.hasNext())
103                {
104                    boolean match = false;
105                    
106                    Object next = req.next();
107                    
108                    if (next instanceof ItemStack)
109                    {
110                        match = checkItemEquals((ItemStack)next, slot);
111                    }
112                    else if (next instanceof ArrayList)
113                    {
114                        for (ItemStack item : (ArrayList<ItemStack>)next)
115                        {
116                            match = match || checkItemEquals(item, slot);
117                        }
118                    }
119
120                    if (match)
121                    {
122                        inRecipe = true;
123                        required.remove(next);
124                        break;
125                    }
126                }
127
128                if (!inRecipe)
129                {
130                    return false;
131                }
132            }
133        }
134
135        return required.isEmpty();
136    }
137    
138    private boolean checkItemEquals(ItemStack target, ItemStack input)
139    {
140        return (target.itemID == input.itemID && (target.getItemDamage() == -1 || target.getItemDamage() == input.getItemDamage()));
141    }
142
143    /**
144     * Returns the input for this recipe, any mod accessing this value should never 
145     * manipulate the values in this array as it will effect the recipe itself.
146     * @return The recipes input vales.
147     */
148    public ArrayList getInput()
149    {
150        return this.input;
151    }
152}