001 package org.bukkit.inventory;
002
003 import java.util.ArrayList;
004 import java.util.Iterator;
005 import java.util.List;
006
007 import org.apache.commons.lang.Validate;
008
009 import org.bukkit.Material;
010 import org.bukkit.material.MaterialData;
011
012 /**
013 * Represents a shapeless recipe, where the arrangement of the ingredients on
014 * the crafting grid does not matter.
015 */
016 public class ShapelessRecipe implements Recipe {
017 private ItemStack output;
018 private List<ItemStack> ingredients = new ArrayList<ItemStack>();
019
020 /**
021 * Create a shapeless recipe to craft the specified ItemStack. The
022 * constructor merely determines the result and type; to set the actual
023 * recipe, you'll need to call the appropriate methods.
024 *
025 * @param result The item you want the recipe to create.
026 * @see ShapelessRecipe#addIngredient(Material)
027 * @see ShapelessRecipe#addIngredient(MaterialData)
028 * @see ShapelessRecipe#addIngredient(Material,int)
029 * @see ShapelessRecipe#addIngredient(int,Material)
030 * @see ShapelessRecipe#addIngredient(int,MaterialData)
031 * @see ShapelessRecipe#addIngredient(int,Material,int)
032 */
033 public ShapelessRecipe(ItemStack result) {
034 this.output = new ItemStack(result);
035 }
036
037 /**
038 * Adds the specified ingredient.
039 *
040 * @param ingredient The ingredient to add.
041 * @return The changed recipe, so you can chain calls.
042 */
043 public ShapelessRecipe addIngredient(MaterialData ingredient) {
044 return addIngredient(1, ingredient);
045 }
046
047 /**
048 * Adds the specified ingredient.
049 *
050 * @param ingredient The ingredient to add.
051 * @return The changed recipe, so you can chain calls.
052 */
053 public ShapelessRecipe addIngredient(Material ingredient) {
054 return addIngredient(1, ingredient, 0);
055 }
056
057 /**
058 * Adds the specified ingredient.
059 *
060 * @param ingredient The ingredient to add.
061 * @param rawdata The data value, or -1 to allow any data value.
062 * @return The changed recipe, so you can chain calls.
063 * @deprecated Magic value
064 */
065 @Deprecated
066 public ShapelessRecipe addIngredient(Material ingredient, int rawdata) {
067 return addIngredient(1, ingredient, rawdata);
068 }
069
070 /**
071 * Adds multiples of the specified ingredient.
072 *
073 * @param count How many to add (can't be more than 9!)
074 * @param ingredient The ingredient to add.
075 * @return The changed recipe, so you can chain calls.
076 */
077 public ShapelessRecipe addIngredient(int count, MaterialData ingredient) {
078 return addIngredient(count, ingredient.getItemType(), ingredient.getData());
079 }
080
081 /**
082 * Adds multiples of the specified ingredient.
083 *
084 * @param count How many to add (can't be more than 9!)
085 * @param ingredient The ingredient to add.
086 * @return The changed recipe, so you can chain calls.
087 */
088 public ShapelessRecipe addIngredient(int count, Material ingredient) {
089 return addIngredient(count, ingredient, 0);
090 }
091
092 /**
093 * Adds multiples of the specified ingredient.
094 *
095 * @param count How many to add (can't be more than 9!)
096 * @param ingredient The ingredient to add.
097 * @param rawdata The data value, or -1 to allow any data value.
098 * @return The changed recipe, so you can chain calls.
099 * @deprecated Magic value
100 */
101 @Deprecated
102 public ShapelessRecipe addIngredient(int count, Material ingredient, int rawdata) {
103 Validate.isTrue(ingredients.size() + count <= 9, "Shapeless recipes cannot have more than 9 ingredients");
104
105 // -1 is the old wildcard, map to Short.MAX_VALUE as the new one
106 if (rawdata == -1) {
107 rawdata = Short.MAX_VALUE;
108 }
109
110 while (count-- > 0) {
111 ingredients.add(new ItemStack(ingredient, 1, (short) rawdata));
112 }
113 return this;
114 }
115
116 /**
117 * Removes an ingredient from the list. If the ingredient occurs multiple
118 * times, only one instance of it is removed. Only removes exact matches,
119 * with a data value of 0.
120 *
121 * @param ingredient The ingredient to remove
122 * @return The changed recipe.
123 */
124 public ShapelessRecipe removeIngredient(Material ingredient) {
125 return removeIngredient(ingredient, 0);
126 }
127
128 /**
129 * Removes an ingredient from the list. If the ingredient occurs multiple
130 * times, only one instance of it is removed. If the data value is -1,
131 * only ingredients with a -1 data value will be removed.
132 *
133 * @param ingredient The ingredient to remove
134 * @return The changed recipe.
135 */
136 public ShapelessRecipe removeIngredient(MaterialData ingredient) {
137 return removeIngredient(ingredient.getItemType(), ingredient.getData());
138 }
139
140 /**
141 * Removes multiple instances of an ingredient from the list. If there are
142 * less instances then specified, all will be removed. Only removes exact
143 * matches, with a data value of 0.
144 *
145 * @param count The number of copies to remove.
146 * @param ingredient The ingredient to remove
147 * @return The changed recipe.
148 */
149 public ShapelessRecipe removeIngredient(int count, Material ingredient) {
150 return removeIngredient(count, ingredient, 0);
151 }
152
153 /**
154 * Removes multiple instances of an ingredient from the list. If there are
155 * less instances then specified, all will be removed. If the data value
156 * is -1, only ingredients with a -1 data value will be removed.
157 *
158 * @param count The number of copies to remove.
159 * @param ingredient The ingredient to remove.
160 * @return The changed recipe.
161 */
162 public ShapelessRecipe removeIngredient(int count, MaterialData ingredient) {
163 return removeIngredient(count, ingredient.getItemType(), ingredient.getData());
164 }
165
166 /**
167 * Removes an ingredient from the list. If the ingredient occurs multiple
168 * times, only one instance of it is removed. If the data value is -1,
169 * only ingredients with a -1 data value will be removed.
170 *
171 * @param ingredient The ingredient to remove
172 * @param rawdata The data value;
173 * @return The changed recipe.
174 * @deprecated Magic value
175 */
176 @Deprecated
177 public ShapelessRecipe removeIngredient(Material ingredient, int rawdata) {
178 return removeIngredient(1, ingredient, rawdata);
179 }
180
181 /**
182 * Removes multiple instances of an ingredient from the list. If there are
183 * less instances then specified, all will be removed. If the data value
184 * is -1, only ingredients with a -1 data value will be removed.
185 *
186 * @param count The number of copies to remove.
187 * @param ingredient The ingredient to remove.
188 * @param rawdata The data value.
189 * @return The changed recipe.
190 * @deprecated Magic value
191 */
192 @Deprecated
193 public ShapelessRecipe removeIngredient(int count, Material ingredient, int rawdata) {
194 Iterator<ItemStack> iterator = ingredients.iterator();
195 while (count > 0 && iterator.hasNext()) {
196 ItemStack stack = iterator.next();
197 if (stack.getType() == ingredient && stack.getDurability() == rawdata) {
198 iterator.remove();
199 count--;
200 }
201 }
202 return this;
203 }
204
205 /**
206 * Get the result of this recipe.
207 *
208 * @return The result stack.
209 */
210 public ItemStack getResult() {
211 return output.clone();
212 }
213
214 /**
215 * Get the list of ingredients used for this recipe.
216 *
217 * @return The input list
218 */
219 public List<ItemStack> getIngredientList() {
220 ArrayList<ItemStack> result = new ArrayList<ItemStack>(ingredients.size());
221 for (ItemStack ingredient : ingredients) {
222 result.add(ingredient.clone());
223 }
224 return result;
225 }
226 }