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 * Gets the integer ID for the specified item stack. 174 * If the item stack is not linked to any ore, this will return -1 and no new entry will be created. 175 * 176 * @param itemStack The item stack of the ore. 177 * @return A number representing the ID for this ore type, or -1 if couldn't find it. 178 */ 179 public static int getOreID(ItemStack itemStack) 180 { 181 if( itemStack == null ) 182 return -1; 183 184 for(int oreID : oreStacks.keySet()) 185 { 186 for(ItemStack target : oreStacks.get(oreID)) 187 { 188 if(itemStack.itemID == target.itemID && (target.getItemDamage() == -1 || itemStack.getItemDamage() == target.getItemDamage())) 189 return oreID; 190 } 191 } 192 return -1; // didn't find it. 193 } 194 195 /** 196 * Retrieves the ArrayList of items that are registered to this ore type. 197 * Creates the list as empty if it did not exist. 198 * 199 * @param name The ore name, directly calls getOreID 200 * @return An arrayList containing ItemStacks registered for this ore 201 */ 202 public static ArrayList<ItemStack> getOres(String name) 203 { 204 return getOres(getOreID(name)); 205 } 206 207 /** 208 * Retrieves a list of all unique ore names that are already registered. 209 * 210 * @return All unique ore names that are currently registered. 211 */ 212 public static String[] getOreNames() 213 { 214 return oreIDs.keySet().toArray(new String[0]); 215 } 216 217 /** 218 * Retrieves the ArrayList of items that are registered to this ore type. 219 * Creates the list as empty if it did not exist. 220 * 221 * @param id The ore ID, see getOreID 222 * @return An arrayList containing ItemStacks registered for this ore 223 */ 224 public static ArrayList<ItemStack> getOres(Integer id) 225 { 226 ArrayList<ItemStack> val = oreStacks.get(id); 227 if (val == null) 228 { 229 val = new ArrayList<ItemStack>(); 230 oreStacks.put(id, val); 231 } 232 return val; 233 } 234 235 private static boolean containsMatch(boolean strict, ItemStack[] inputs, ItemStack... targets) 236 { 237 for (ItemStack input : inputs) 238 { 239 for (ItemStack target : targets) 240 { 241 if (itemMatches(target, input, strict)) 242 { 243 return true; 244 } 245 } 246 } 247 return false; 248 } 249 250 public static boolean itemMatches(ItemStack target, ItemStack input, boolean strict) 251 { 252 if (input == null && target != null || input != null && target == null) 253 { 254 return false; 255 } 256 return (target.itemID == input.itemID && ((target.getItemDamage() == -1 && !strict) || target.getItemDamage() == input.getItemDamage())); 257 } 258 259 //Convenience functions that make for cleaner code mod side. They all drill down to registerOre(String, int, ItemStack) 260 public static void registerOre(String name, Item ore){ registerOre(name, new ItemStack(ore)); } 261 public static void registerOre(String name, Block ore){ registerOre(name, new ItemStack(ore)); } 262 public static void registerOre(String name, ItemStack ore){ registerOre(name, getOreID(name), ore); } 263 public static void registerOre(int id, Item ore){ registerOre(id, new ItemStack(ore)); } 264 public static void registerOre(int id, Block ore){ registerOre(id, new ItemStack(ore)); } 265 public static void registerOre(int id, ItemStack ore){ registerOre(getOreName(id), id, ore); } 266 267 /** 268 * Registers a ore item into the dictionary. 269 * Raises the registerOre function in all registered handlers. 270 * 271 * @param name The name of the ore 272 * @param id The ID of the ore 273 * @param ore The ore's ItemStack 274 */ 275 private static void registerOre(String name, int id, ItemStack ore) 276 { 277 ArrayList<ItemStack> ores = getOres(id); 278 ore = ore.copy(); 279 ores.add(ore); 280 MinecraftForge.EVENT_BUS.post(new OreRegisterEvent(name, ore)); 281 } 282 283 public static class OreRegisterEvent extends Event 284 { 285 public final String Name; 286 public final ItemStack Ore; 287 288 public OreRegisterEvent(String name, ItemStack ore) 289 { 290 this.Name = name; 291 this.Ore = ore; 292 } 293 } 294 }