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