001 package net.minecraftforge.oredict; 002 003 import java.util.ArrayList; 004 import java.util.HashMap; 005 006 import net.minecraft.src.Block; 007 import net.minecraft.src.IRecipe; 008 import net.minecraft.src.InventoryCrafting; 009 import net.minecraft.src.Item; 010 import net.minecraft.src.ItemStack; 011 import net.minecraft.src.ShapedRecipes; 012 import net.minecraft.src.World; 013 014 public class ShapedOreRecipe implements IRecipe 015 { 016 //Added in for future ease of change, but hard coded for now. 017 private static final int MAX_CRAFT_GRID_WIDTH = 3; 018 private static final int MAX_CRAFT_GRID_HEIGHT = 3; 019 020 private ItemStack output = null; 021 private Object[] input = null; 022 private int width = 0; 023 private int height = 0; 024 private boolean mirriored = true; 025 026 public ShapedOreRecipe(Block result, Object... recipe){ this(result, true, recipe);} 027 public ShapedOreRecipe(Item result, Object... recipe){ this(result, true, recipe); } 028 public ShapedOreRecipe(ItemStack result, Object... recipe){ this(result, true, recipe); } 029 public ShapedOreRecipe(Block result, boolean mirrior, Object... recipe){ this(new ItemStack(result), mirrior, recipe);} 030 public ShapedOreRecipe(Item result, boolean mirrior, Object... recipe){ this(new ItemStack(result), mirrior, recipe); } 031 032 public ShapedOreRecipe(ItemStack result, boolean mirrior, Object... recipe) 033 { 034 output = result.copy(); 035 mirriored = mirrior; 036 037 String shape = ""; 038 int idx = 0; 039 040 if (recipe[idx] instanceof String[]) 041 { 042 String[] parts = ((String[])recipe[idx++]); 043 044 for (String s : parts) 045 { 046 width = s.length(); 047 shape += s; 048 } 049 050 height = parts.length; 051 } 052 else 053 { 054 while (recipe[idx] instanceof String) 055 { 056 String s = (String)recipe[idx++]; 057 shape += s; 058 width = s.length(); 059 height++; 060 } 061 } 062 063 if (width * height != shape.length()) 064 { 065 String ret = "Invalid shaped ore recipe: "; 066 for (Object tmp : recipe) 067 { 068 ret += tmp + ", "; 069 } 070 ret += output; 071 throw new RuntimeException(ret); 072 } 073 074 HashMap<Character, Object> itemMap = new HashMap<Character, Object>(); 075 076 for (; idx < recipe.length; idx += 2) 077 { 078 Character chr = (Character)recipe[idx]; 079 Object in = recipe[idx + 1]; 080 Object val = null; 081 082 if (in instanceof ItemStack) 083 { 084 itemMap.put(chr, ((ItemStack)in).copy()); 085 } 086 else if (in instanceof Item) 087 { 088 itemMap.put(chr, new ItemStack((Item)in)); 089 } 090 else if (in instanceof Block) 091 { 092 itemMap.put(chr, new ItemStack((Block)in, 1, -1)); 093 } 094 else if (in instanceof String) 095 { 096 itemMap.put(chr, OreDictionary.getOres((String)in)); 097 } 098 else 099 { 100 String ret = "Invalid shaped ore recipe: "; 101 for (Object tmp : recipe) 102 { 103 ret += tmp + ", "; 104 } 105 ret += output; 106 throw new RuntimeException(ret); 107 } 108 } 109 110 input = new Object[width * height]; 111 int x = 0; 112 for (char chr : shape.toCharArray()) 113 { 114 input[x++] = itemMap.get(chr); 115 } 116 } 117 118 @Override 119 public ItemStack getCraftingResult(InventoryCrafting var1){ return output.copy(); } 120 121 @Override 122 public int getRecipeSize(){ return input.length; } 123 124 @Override 125 public ItemStack getRecipeOutput(){ return output; } 126 127 @Override 128 public boolean matches(InventoryCrafting inv, World world) 129 { 130 for (int x = 0; x <= MAX_CRAFT_GRID_WIDTH - width; x++) 131 { 132 for (int y = 0; y <= MAX_CRAFT_GRID_HEIGHT - height; ++y) 133 { 134 if (checkMatch(inv, x, y, true)) 135 { 136 return true; 137 } 138 139 if (mirriored && checkMatch(inv, x, y, false)) 140 { 141 return true; 142 } 143 } 144 } 145 146 return false; 147 } 148 149 private boolean checkMatch(InventoryCrafting inv, int startX, int startY, boolean mirrior) 150 { 151 for (int x = 0; x < MAX_CRAFT_GRID_WIDTH; x++) 152 { 153 for (int y = 0; y < MAX_CRAFT_GRID_HEIGHT; y++) 154 { 155 int subX = x - startX; 156 int subY = y - startY; 157 Object target = null; 158 159 if (subX >= 0 && subY >= 0 && subX < width && subY < height) 160 { 161 if (mirrior) 162 { 163 target = input[width - subX - 1 + subY * width]; 164 } 165 else 166 { 167 target = input[subX + subY * width]; 168 } 169 } 170 171 ItemStack slot = inv.getStackInRowAndColumn(x, y); 172 173 if (target instanceof ItemStack) 174 { 175 if (!checkItemEquals((ItemStack)target, slot)) 176 { 177 return false; 178 } 179 } 180 else if (target instanceof ArrayList) 181 { 182 boolean matched = false; 183 184 for (ItemStack item : (ArrayList<ItemStack>)target) 185 { 186 matched = matched || checkItemEquals(item, slot); 187 } 188 189 if (!matched) 190 { 191 return false; 192 } 193 } 194 else if (target == null && slot != null) 195 { 196 return false; 197 } 198 } 199 } 200 201 return true; 202 } 203 204 private boolean checkItemEquals(ItemStack target, ItemStack input) 205 { 206 if (input == null && target != null || input != null && target == null) 207 { 208 return false; 209 } 210 return (target.itemID == input.itemID && (target.getItemDamage() == -1 || target.getItemDamage() == input.getItemDamage())); 211 } 212 213 public void setMirriored(boolean mirrior) 214 { 215 mirriored = mirrior; 216 } 217 }