From 32100207e8518b3eeacefb54b02413191f196470 Mon Sep 17 00:00:00 2001 From: LexManos Date: Sat, 9 Jun 2012 23:18:58 -0700 Subject: [PATCH] New Ore Dictionary recipies. Allows for simpler Ore Dictionary integration with recipies. IOreHandler should no longer be used. --- .../minecraft/src/forge/MinecraftForge.java | 67 ++---- .../src/forge/oredict/OreDictionary.java | 136 +++++++++++ .../src/forge/oredict/ShapedOreRecipe.java | 216 ++++++++++++++++++ .../src/forge/oredict/ShapelessOreRecipe.java | 119 ++++++++++ 4 files changed, 492 insertions(+), 46 deletions(-) create mode 100644 forge/forge_common/net/minecraft/src/forge/oredict/OreDictionary.java create mode 100644 forge/forge_common/net/minecraft/src/forge/oredict/ShapedOreRecipe.java create mode 100644 forge/forge_common/net/minecraft/src/forge/oredict/ShapelessOreRecipe.java diff --git a/forge/forge_common/net/minecraft/src/forge/MinecraftForge.java b/forge/forge_common/net/minecraft/src/forge/MinecraftForge.java index e93f1db45..3cd5f93bd 100755 --- a/forge/forge_common/net/minecraft/src/forge/MinecraftForge.java +++ b/forge/forge_common/net/minecraft/src/forge/MinecraftForge.java @@ -18,6 +18,7 @@ import net.minecraft.src.Packet; import net.minecraft.src.Packet131MapData; import net.minecraft.src.Packet132TileEntityData; import net.minecraft.src.World; +import net.minecraft.src.forge.oredict.OreDictionary; import java.util.*; import java.util.Map.Entry; @@ -181,72 +182,45 @@ public class MinecraftForge // Ore Dictionary // ------------------------------------------------------------ - private static LinkedList oreHandlers = new LinkedList(); - private static TreeMap> oreDict = new TreeMap>(); - - /** Register a new ore handler. This will automatically call the handler - * with all current ores during registration, and every time a new ore is - * added later. - */ + //Deprecated in favor of OreDictionary.registerOreHandler + @Deprecated public static void registerOreHandler(IOreHandler handler) { - oreHandlers.add(handler); - - for (String key : oreDict.keySet()) - { - List ores = oreDict.get(key); - for (ItemStack stack : ores) - { - handler.registerOre(key, stack); - } - } + OreDictionary.registerOreHandler(handler); } - /** Register a new item with the ore dictionary. - * @param oreClass The string class of the ore. - * @param ore The ItemStack for the ore. - */ + //Deprecated in favor of OreDictionary.registerOre + @Deprecated public static void registerOre(String oreClass, ItemStack ore) { - List orelist = oreDict.get(oreClass); - if (orelist == null) - { - orelist = new ArrayList(); - oreDict.put(oreClass, orelist); - } - orelist.add(ore); - for (IOreHandler ioh : oreHandlers) - { - ioh.registerOre(oreClass, ore); - } + OreDictionary.registerOre(oreClass, ore); } - /** Get the list of ores in a given class. - */ + //Deprecated in favor of OreDictionary.getOres + @Deprecated public static List getOreClass(String oreClass) { - return oreDict.get(oreClass); + return OreDictionary.getOres(oreClass); } + //Deprecated in favor of the Ore recipes, and because it is ugly as heck. + @Deprecated public static class OreQuery implements Iterable { Object[] proto; public class OreQueryIterator implements Iterator { - LinkedList itering; - LinkedList output; + LinkedList itering = new LinkedList(); + LinkedList output = new LinkedList(); private OreQueryIterator() { - itering = new LinkedList(); - output = new LinkedList(); - - for (int i = 0; i < proto.length; i++) + for (Object input : proto) { - if (proto[i] instanceof Collection) + if (input instanceof Collection) { - Iterator it = ((Collection)proto[i]).iterator(); + Iterator it = ((Collection)input).iterator(); if (!it.hasNext()) { output = null; @@ -257,8 +231,8 @@ public class MinecraftForge } else { - itering.addLast(proto[i]); - output.addLast(proto[i]); + itering.addLast(input); + output.addLast(input); } } } @@ -271,7 +245,6 @@ public class MinecraftForge public Object[] next() { Object[] tr = output.toArray(); - Object to; while (true) { @@ -332,6 +305,8 @@ public class MinecraftForge /** Generate all valid legal recipe combinations. Any Lists in pattern * will be fully expanded to all valid combinations. */ + //Deprecated in favor of the new Ore Recipe system + @Deprecated public static OreQuery generateRecipes(Object... pattern) { return new OreQuery(pattern); diff --git a/forge/forge_common/net/minecraft/src/forge/oredict/OreDictionary.java b/forge/forge_common/net/minecraft/src/forge/oredict/OreDictionary.java new file mode 100644 index 000000000..ac2e080f1 --- /dev/null +++ b/forge/forge_common/net/minecraft/src/forge/oredict/OreDictionary.java @@ -0,0 +1,136 @@ +package net.minecraft.src.forge.oredict; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import net.minecraft.src.Block; +import net.minecraft.src.Item; +import net.minecraft.src.ItemStack; +import net.minecraft.src.forge.IOreHandler; + +public class OreDictionary +{ + private static int maxID = 0; + private static HashMap oreIDs = new HashMap(); + private static HashMap> oreStacks = new HashMap>(); + private static ArrayList oreHandlers = new ArrayList(); + + /** + * Gets the integer ID for the specified ore name. + * If the name does not have a ID it assigns it a new one. + * + * @param name The unique name for this ore 'oreIron', 'ingotIron', etc.. + * @return A number representing the ID for this ore type + */ + public static int getOreID(String name) + { + Integer val = oreIDs.get(name); + if (val == null) + { + val = maxID++; + oreIDs.put(name, val); + oreStacks.put(val, new ArrayList()); + } + return val; + } + + /** + * Reverse of getOreID, will not create new entries. + * + * @param id The ID to translate to a string + * @return The String name, or "Unknown" if not found. + */ + public static String getOreName(int id) + { + for (Map.Entry entry : oreIDs.entrySet()) + { + if (id == entry.getValue()) + { + return entry.getKey(); + } + } + return "Unknown"; + } + + /** + * Retrieves the ArrayList of items that are registered to this ore type. + * Creates the list as empty if it did not exist. + * + * @param id The ore ID, see getOreID + * @return An arrayList containing ItemStacks registered for this ore + */ + public static ArrayList getOres(String name) + { + return getOres(getOreID(name)); + } + + /** + * Retrieves the ArrayList of items that are registered to this ore type. + * Creates the list as empty if it did not exist. + * + * @param id The ore ID, see getOreID + * @return An arrayList containing ItemStacks registered for this ore + */ + public static ArrayList getOres(Integer id) + { + ArrayList val = oreStacks.get(id); + if (val == null) + { + val = new ArrayList(); + oreStacks.put(id, val); + } + return val; + } + + /** + * Register a new ore handler. + * This will automatically call the handler with all current ores during + * registration, and every time a new ore is added later. + * + * @param handler The Ore Handler + */ + public static void registerOreHandler(IOreHandler handler) + { + oreHandlers.add(handler); + + for (Map.Entry entry : oreIDs.entrySet()) + { + List ores = getOres(entry.getValue()); + for (ItemStack stack : ores) + { + handler.registerOre(entry.getKey(), stack); + } + } + } + + //Convenience functions that make for cleaner code mod side. They all drill down to registerOre(String, int, ItemStack) + public static void registerOre(String name, Item ore){ registerOre(name, new ItemStack(ore)); } + public static void registerOre(String name, Block ore){ registerOre(name, new ItemStack(ore)); } + public static void registerOre(String name, ItemStack ore){ registerOre(name, getOreID(name), ore); } + public static void registerOre(int id, Item ore){ registerOre(id, new ItemStack(ore)); } + public static void registerOre(int id, Block ore){ registerOre(id, new ItemStack(ore)); } + public static void registerOre(int id, ItemStack ore){ registerOre(getOreName(id), id, ore); } + + /** + * Registers a ore item into the dictionary. + * Raises the registerOre function in all registered handlers. + * + * @param name The name of the ore + * @param id The ID of the ore + * @param ore The ore's ItemStack + */ + private static void registerOre(String name, int id, ItemStack ore) + { + ArrayList ores = getOres(id); + ore = ore.copy(); + ores.add(ore); + + for (IOreHandler handler : oreHandlers) + { + handler.registerOre(name, ore); + } + } +} diff --git a/forge/forge_common/net/minecraft/src/forge/oredict/ShapedOreRecipe.java b/forge/forge_common/net/minecraft/src/forge/oredict/ShapedOreRecipe.java new file mode 100644 index 000000000..bb3fed5ea --- /dev/null +++ b/forge/forge_common/net/minecraft/src/forge/oredict/ShapedOreRecipe.java @@ -0,0 +1,216 @@ +package net.minecraft.src.forge.oredict; + +import java.util.ArrayList; +import java.util.HashMap; + +import net.minecraft.src.Block; +import net.minecraft.src.IRecipe; +import net.minecraft.src.InventoryCrafting; +import net.minecraft.src.Item; +import net.minecraft.src.ItemStack; +import net.minecraft.src.ShapedRecipes; + +public class ShapedOreRecipe implements IRecipe +{ + //Added in for future ease of change, but hard coded for now. + 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; + private int width = 0; + private int height = 0; + private boolean mirriored = true; + + public ShapedOreRecipe(Block result, Object... recipe){ this(result, true, recipe);} + public ShapedOreRecipe(Item result, Object... recipe){ this(result, true, recipe); } + public ShapedOreRecipe(ItemStack result, Object... recipe){ this(result, true, recipe); } + public ShapedOreRecipe(Block result, boolean mirrior, Object... recipe){ this(new ItemStack(result), mirrior, recipe);} + public ShapedOreRecipe(Item result, boolean mirrior, Object... recipe){ this(new ItemStack(result), mirrior, recipe); } + + public ShapedOreRecipe(ItemStack result, boolean mirrior, Object... recipe) + { + output = result.copy(); + mirriored = mirrior; + + String shape = ""; + int idx = 0; + + 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 itemMap = new HashMap(); + + for (; idx < recipe.length; idx += 2) + { + Character chr = (Character)recipe[idx]; + Object in = recipe[idx + 1]; + Object val = null; + + 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, -1)); + } + 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 var1){ return output.copy(); } + + @Override + public int getRecipeSize(){ return input.length; } + + @Override + public ItemStack getRecipeOutput(){ return output; } + + @Override + public boolean matches(InventoryCrafting inv) + { + 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 (mirriored && checkMatch(inv, x, y, false)) + { + return true; + } + } + } + + return false; + } + + private boolean checkMatch(InventoryCrafting inv, int startX, int startY, boolean mirrior) + { + 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 (mirrior) + { + 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)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; + } + return (target.itemID == input.itemID && (target.getItemDamage() == -1 || target.getItemDamage() == input.getItemDamage())); + } + + public void setMirriored(boolean mirrior) + { + mirriored = mirrior; + } +} diff --git a/forge/forge_common/net/minecraft/src/forge/oredict/ShapelessOreRecipe.java b/forge/forge_common/net/minecraft/src/forge/oredict/ShapelessOreRecipe.java new file mode 100644 index 000000000..84beb9623 --- /dev/null +++ b/forge/forge_common/net/minecraft/src/forge/oredict/ShapelessOreRecipe.java @@ -0,0 +1,119 @@ +package net.minecraft.src.forge.oredict; + +import java.util.ArrayList; +import java.util.Iterator; + +import net.minecraft.src.Block; +import net.minecraft.src.CraftingManager; +import net.minecraft.src.IRecipe; +import net.minecraft.src.InventoryCrafting; +import net.minecraft.src.Item; +import net.minecraft.src.ItemStack; +import net.minecraft.src.ShapelessRecipes; + +public class ShapelessOreRecipe implements IRecipe +{ + private ItemStack output = null; + private ArrayList input = new ArrayList(); + + public ShapelessOreRecipe(Block result, Object... recipe){ this(new ItemStack(result), recipe); } + public ShapelessOreRecipe(Item result, Object... recipe){ this(new ItemStack(result), recipe); } + + public ShapelessOreRecipe(ItemStack result, Object... recipe) + { + output = result.copy(); + for (Object in : recipe) + { + if (in instanceof ItemStack) + { + input.add(((ItemStack)in).copy()); + } + else if (in instanceof Item) + { + input.add(new ItemStack((Item)in)); + } + else if (in instanceof Block) + { + input.add(new ItemStack((Block)in)); + } + else if (in instanceof String) + { + input.add(OreDictionary.getOres((String)in)); + } + else + { + String ret = "Invalid shapeless ore recipe: "; + for (Object tmp : recipe) + { + ret += tmp + ", "; + } + ret += output; + throw new RuntimeException(ret); + } + } + } + + @Override + public int getRecipeSize(){ return input.size(); } + + @Override + public ItemStack getRecipeOutput(){ return output; } + + @Override + public ItemStack getCraftingResult(InventoryCrafting var1){ return output.copy(); } + + @Override + public boolean matches(InventoryCrafting var1) + { + ArrayList required = new ArrayList(input); + + for (int x = 0; x < var1.getSizeInventory(); x++) + { + ItemStack slot = var1.getStackInSlot(x); + + if (slot != null) + { + boolean inRecipe = false; + Iterator req = required.iterator(); + + while (req.hasNext()) + { + boolean match = false; + + Object next = req.next(); + + if (next instanceof ItemStack) + { + match = checkItemEquals((ItemStack)next, slot); + } + else if (next instanceof ArrayList) + { + for (ItemStack item : (ArrayList)next) + { + match = match || checkItemEquals(item, slot); + } + } + + if (match) + { + inRecipe = true; + required.remove(next); + break; + } + } + + if (!inRecipe) + { + return false; + } + } + } + + return required.isEmpty(); + } + + private boolean checkItemEquals(ItemStack target, ItemStack input) + { + return (target.itemID == input.itemID && (target.getItemDamage() == -1 || target.getItemDamage() == input.getItemDamage())); + } +}