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