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 Object val = null; 091 092 if (in instanceof ItemStack) 093 { 094 itemMap.put(chr, ((ItemStack)in).copy()); 095 } 096 else if (in instanceof Item) 097 { 098 itemMap.put(chr, new ItemStack((Item)in)); 099 } 100 else if (in instanceof Block) 101 { 102 itemMap.put(chr, new ItemStack((Block)in, 1, -1)); 103 } 104 else if (in instanceof String) 105 { 106 itemMap.put(chr, OreDictionary.getOres((String)in)); 107 } 108 else 109 { 110 String ret = "Invalid shaped ore recipe: "; 111 for (Object tmp : recipe) 112 { 113 ret += tmp + ", "; 114 } 115 ret += output; 116 throw new RuntimeException(ret); 117 } 118 } 119 120 input = new Object[width * height]; 121 int x = 0; 122 for (char chr : shape.toCharArray()) 123 { 124 input[x++] = itemMap.get(chr); 125 } 126 } 127 128 ShapedOreRecipe(ShapedRecipes recipe, Map<ItemStack, String> replacements) 129 { 130 output = recipe.getRecipeOutput(); 131 width = recipe.recipeWidth; 132 height = recipe.recipeHeight; 133 134 input = new Object[recipe.recipeItems.length]; 135 136 for(int i = 0; i < input.length; i++) 137 { 138 ItemStack ingred = recipe.recipeItems[i]; 139 140 if(ingred == null) continue; 141 142 input[i] = recipe.recipeItems[i]; 143 144 for(Entry<ItemStack, String> replace : replacements.entrySet()) 145 { 146 if(OreDictionary.itemMatches(replace.getKey(), ingred, true)) 147 { 148 input[i] = OreDictionary.getOres(replace.getValue()); 149 break; 150 } 151 } 152 } 153 } 154 155 @Override 156 public ItemStack getCraftingResult(InventoryCrafting var1){ return output.copy(); } 157 158 @Override 159 public int getRecipeSize(){ return input.length; } 160 161 @Override 162 public ItemStack getRecipeOutput(){ return output; } 163 164 @Override 165 public boolean matches(InventoryCrafting inv, World world) 166 { 167 for (int x = 0; x <= MAX_CRAFT_GRID_WIDTH - width; x++) 168 { 169 for (int y = 0; y <= MAX_CRAFT_GRID_HEIGHT - height; ++y) 170 { 171 if (checkMatch(inv, x, y, true)) 172 { 173 return true; 174 } 175 176 if (mirrored && checkMatch(inv, x, y, false)) 177 { 178 return true; 179 } 180 } 181 } 182 183 return false; 184 } 185 186 private boolean checkMatch(InventoryCrafting inv, int startX, int startY, boolean mirror) 187 { 188 for (int x = 0; x < MAX_CRAFT_GRID_WIDTH; x++) 189 { 190 for (int y = 0; y < MAX_CRAFT_GRID_HEIGHT; y++) 191 { 192 int subX = x - startX; 193 int subY = y - startY; 194 Object target = null; 195 196 if (subX >= 0 && subY >= 0 && subX < width && subY < height) 197 { 198 if (mirror) 199 { 200 target = input[width - subX - 1 + subY * width]; 201 } 202 else 203 { 204 target = input[subX + subY * width]; 205 } 206 } 207 208 ItemStack slot = inv.getStackInRowAndColumn(x, y); 209 210 if (target instanceof ItemStack) 211 { 212 if (!checkItemEquals((ItemStack)target, slot)) 213 { 214 return false; 215 } 216 } 217 else if (target instanceof ArrayList) 218 { 219 boolean matched = false; 220 221 for (ItemStack item : (ArrayList<ItemStack>)target) 222 { 223 matched = matched || checkItemEquals(item, slot); 224 } 225 226 if (!matched) 227 { 228 return false; 229 } 230 } 231 else if (target == null && slot != null) 232 { 233 return false; 234 } 235 } 236 } 237 238 return true; 239 } 240 241 private boolean checkItemEquals(ItemStack target, ItemStack input) 242 { 243 if (input == null && target != null || input != null && target == null) 244 { 245 return false; 246 } 247 return (target.itemID == input.itemID && (target.getItemDamage() == -1 || target.getItemDamage() == input.getItemDamage())); 248 } 249 250 public ShapedOreRecipe setMirrored(boolean mirror) 251 { 252 mirrored = mirror; 253 return this; 254 } 255 }