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