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