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 }