    001    package net.minecraftforge.oredict;
    002
    003    import java.util.ArrayList;
    004    import java.util.HashMap;
    005    import java.util.Iterator;
    006    import java.util.List;
    007    import java.util.Map;
    008    import java.util.Map.Entry;
    009
    010    import net.minecraft.src.*;
    011    import net.minecraftforge.common.MinecraftForge;
    012    import net.minecraftforge.event.Event;
    013
    014    public class OreDictionary
    015    {
    016        private static int maxID = 0;
    017        private static HashMap<String, Integer> oreIDs = new HashMap<String, Integer>();
    018        private static HashMap<Integer, ArrayList<ItemStack>> oreStacks = new HashMap<Integer, ArrayList<ItemStack>>();
    019
    020        static {
    021            initVanillaEntries();
    022        }
    023
    024        public static void initVanillaEntries()
    025        {
    026            registerOre("logWood",   new ItemStack(Block.wood, 1, -1));
    027            registerOre("plankWood", new ItemStack(Block.planks, 1, -1));
    028            registerOre("slabWood",  new ItemStack(Block.woodSingleSlab, 1, -1));
    029            registerOre("stairWood", Block.stairCompactPlanks);
    030            registerOre("stairWood", Block.stairsWoodBirch);
    031            registerOre("stairWood", Block.stairsWoodJungle);
    032            registerOre("stairWood", Block.stairsWoodSpruce);
    033            registerOre("stickWood", Item.stick);
    034
    035            // Build our list of items to replace with ore tags
    036            Map<ItemStack, String> replacements = new HashMap<ItemStack, String>();
    037            replacements.put(new ItemStack(Block.planks, 1, -1), "plankWood");
    038            replacements.put(new ItemStack(Item.stick), "stickWood");
    039
    040            // Register dyes
    041            String[] dyes =
    042            {
    043                "dyeBlack",
    044                "dyeRed",
    045                "dyeGreen",
    046                "dyeBrown",
    047                "dyeBlue",
    048                "dyePurple",
    049                "dyeCyan",
    050                "dyeLightGray",
    051                "dyeGray",
    052                "dyePink",
    053                "dyeLime",
    054                "dyeYellow",
    055                "dyeLightBlue",
    056                "dyeMagenta",
    057                "dyeOrange",
    058                "dyeWhite"
    059            };
    060
    061            for(int i = 0; i < 16; i++)
    062            {
    063                ItemStack dye = new ItemStack(Item.dyePowder, 1, i);
    064                registerOre(dyes[i], dye);
    065                replacements.put(dye, dyes[i]);
    066            }
    067
    068            ItemStack[] replaceStacks = replacements.keySet().toArray(new ItemStack[0]);
    069
    070            // Ignore recipes for the following items
    071            ItemStack[] exclusions = new ItemStack[]
    072            {
    073                new ItemStack(Block.blockLapis),
    074                new ItemStack(Item.cookie),
    075            };
    076
    077            List recipes = CraftingManager.getInstance().getRecipeList();
    078            List<IRecipe> recipesToRemove = new ArrayList<IRecipe>();
    079            List<IRecipe> recipesToAdd = new ArrayList<IRecipe>();
    080
    081            // Search vanilla recipes for recipes to replace
    082            for(Object obj : recipes)
    083            {
    084                if(obj instanceof ShapedRecipes)
    085                {
    086                    ShapedRecipes recipe = (ShapedRecipes)obj;
    087                    ItemStack output = recipe.getRecipeOutput();
    088                    if (output != null && containsMatch(false, exclusions, output))
    089                    {
    090                        continue;
    091                    }
    092
    093                    if(containsMatch(true, recipe.recipeItems, replaceStacks))
    094                    {
    095                        recipesToRemove.add(recipe);
    096                        recipesToAdd.add(new ShapedOreRecipe(recipe, replacements));
    097                    }
    098                }
    099                else if(obj instanceof ShapelessRecipes)
    100                {
    101                    ShapelessRecipes recipe = (ShapelessRecipes)obj;
    102                    ItemStack output = recipe.getRecipeOutput();
    103                    if (output != null && containsMatch(false, exclusions, output))
    104                    {
    105                        continue;
    106                    }
    107
    108                    if(containsMatch(true, (ItemStack[])recipe.recipeItems.toArray(new ItemStack[0]), replaceStacks))
    109                    {
    110                        recipesToRemove.add((IRecipe)obj);
    111                        IRecipe newRecipe = new ShapelessOreRecipe(recipe, replacements);
    112                        recipesToAdd.add(newRecipe);
    113                    }
    114                }
    115            }
    116
    117            recipes.removeAll(recipesToRemove);
    118            recipes.addAll(recipesToAdd);
    119            System.out.println(recipesToRemove.size() + " " + recipesToAdd.size());
    120        }
    121
    122        /**
    123         * Gets the integer ID for the specified ore name.
    124         * If the name does not have a ID it assigns it a new one.
    125         *
    126         * @param name The unique name for this ore 'oreIron', 'ingotIron', etc..
    127         * @return A number representing the ID for this ore type
    128         */
    129        public static int getOreID(String name)
    130        {
    131            Integer val = oreIDs.get(name);
    132            if (val == null)
    133            {
    134                val = maxID++;
    135                oreIDs.put(name, val);
    136                oreStacks.put(val, new ArrayList<ItemStack>());
    137            }
    138            return val;
    139        }
    140
    141        /**
    142         * Reverse of getOreID, will not create new entries.
    143         *
    144         * @param id The ID to translate to a string
    145         * @return The String name, or "Unknown" if not found.
    146         */
    147        public static String getOreName(int id)
    148        {
    149            for (Map.Entry<String, Integer> entry : oreIDs.entrySet())
    150            {
    151                if (id == entry.getValue())
    152                {
    153                    return entry.getKey();
    154                }
    155            }
    156            return "Unknown";
    157        }
    158
    159        /**
    160         * Retrieves the ArrayList of items that are registered to this ore type.
    161         * Creates the list as empty if it did not exist.
    162         *
    163         * @param name The ore name, directly calls getOreID
    164         * @return An arrayList containing ItemStacks registered for this ore
    165         */
    166        public static ArrayList<ItemStack> getOres(String name)
    167        {
    168            return getOres(getOreID(name));
    169        }
    170
    171        /**
    172         * Retrieves a list of all unique ore names that are already registered.
    173         *
    174         * @return All unique ore names that are currently registered.
    175         */
    176        public static String[] getOreNames()
    177        {
    178            return oreIDs.keySet().toArray(new String[0]);
    179        }
    180
    181        /**
    182         * Retrieves the ArrayList of items that are registered to this ore type.
    183         * Creates the list as empty if it did not exist.
    184         *
    185         * @param id The ore ID, see getOreID
    186         * @return An arrayList containing ItemStacks registered for this ore
    187         */
    188        public static ArrayList<ItemStack> getOres(Integer id)
    189        {
    190            ArrayList<ItemStack> val = oreStacks.get(id);
    191            if (val == null)
    192            {
    193                val = new ArrayList<ItemStack>();
    194                oreStacks.put(id, val);
    195            }
    196            return val;
    197        }
    198
    199        private static boolean containsMatch(boolean strict, ItemStack[] inputs, ItemStack... targets)
    200        {
    201            for (ItemStack input : inputs)
    202            {
    203                for (ItemStack target : targets)
    204                {
    205                    if (itemMatches(target, input, strict))
    206                    {
    207                        return true;
    208                    }
    209                }
    210            }
    211            return false;
    212        }
    213
    214        public static boolean itemMatches(ItemStack target, ItemStack input, boolean strict)
    215        {
    216            if (input == null && target != null || input != null && target == null)
    217            {
    218                return false;
    219            }
    220            return (target.itemID == input.itemID && ((target.getItemDamage() == -1 && !strict) || target.getItemDamage() == input.getItemDamage()));
    221        }
    222
    223        //Convenience functions that make for cleaner code mod side. They all drill down to registerOre(String, int, ItemStack)
    224        public static void registerOre(String name, Item      ore){ registerOre(name, new ItemStack(ore));  }
    225        public static void registerOre(String name, Block     ore){ registerOre(name, new ItemStack(ore));  }
    226        public static void registerOre(String name, ItemStack ore){ registerOre(name, getOreID(name), ore); }
    227        public static void registerOre(int    id,   Item      ore){ registerOre(id,   new ItemStack(ore));  }
    228        public static void registerOre(int    id,   Block     ore){ registerOre(id,   new ItemStack(ore));  }
    229        public static void registerOre(int    id,   ItemStack ore){ registerOre(getOreName(id), id, ore);   }
    230
    231        /**
    232         * Registers a ore item into the dictionary.
    233         * Raises the registerOre function in all registered handlers.
    234         *
    235         * @param name The name of the ore
    236         * @param id The ID of the ore
    237         * @param ore The ore's ItemStack
    238         */
    239        private static void registerOre(String name, int id, ItemStack ore)
    240        {
    241            ArrayList<ItemStack> ores = getOres(id);
    242            ore = ore.copy();
    243            ores.add(ore);
    244            MinecraftForge.EVENT_BUS.post(new OreRegisterEvent(name, ore));
    245        }
    246
    247        public static class OreRegisterEvent extends Event
    248        {
    249            public final String Name;
    250            public final ItemStack Ore;
    251
    252            public OreRegisterEvent(String name, ItemStack ore)
    253            {
    254                this.Name = name;
    255                this.Ore = ore;
    256            }
    257        }
    258    }