package org.bukkit.inventory; import org.apache.commons.lang.Validate; import org.bukkit.Material; import org.bukkit.material.MaterialData; import java.util.HashMap; import java.util.Map; /** * Represents a shaped (ie normal) crafting recipe. */ public class ShapedRecipe implements Recipe { private ItemStack output; private String[] rows; private Map<Character, ItemStack> ingredients = new HashMap<Character, ItemStack>(); /** * Create a shaped recipe to craft the specified ItemStack. The * constructor merely determines the result and type; to set the actual * recipe, you'll need to call the appropriate methods. * * @param result The item you want the recipe to create. * @see ShapedRecipe#shape(String...) * @see ShapedRecipe#setIngredient(char, Material) * @see ShapedRecipe#setIngredient(char, Material, int) * @see ShapedRecipe#setIngredient(char, MaterialData) */ public ShapedRecipe(ItemStack result) { this.output = new ItemStack(result); } /** * Set the shape of this recipe to the specified rows. Each character * represents a different ingredient; exactly what each character * represents is set separately. The first row supplied corresponds with * the upper most part of the recipe on the workbench e.g. if all three * rows are supplies the first string represents the top row on the * workbench. * * @param shape The rows of the recipe (up to 3 rows). * @return The changed recipe, so you can chain calls. */ public ShapedRecipe shape(final String... shape) { Validate.notNull(shape, "Must provide a shape"); Validate.isTrue(shape.length > 0 && shape.length < 4, "Crafting recipes should be 1, 2, 3 rows, not ", shape.length); for(String row : shape) { Validate.notNull(row, "Shape cannot have null rows"); Validate.isTrue(row.length() > 0 && row.length() < 4, "Crafting rows should be 1, 2, or 3 characters, not ", row.length()); } this.rows = new String[shape.length]; for(int i = 0; i < shape.length; i++) { this.rows[i] = shape[i]; } // Remove character mappings for characters that no longer exist in the shape HashMap<Character, ItemStack> newIngredients = new HashMap<Character, ItemStack>(); for(String row : shape) { for(Character c : row.toCharArray()) { newIngredients.put(c, ingredients.get(c)); } } this.ingredients = newIngredients; return this; } /** * Sets the material that a character in the recipe shape refers to. * * @param key The character that represents the ingredient in the shape. * @param ingredient The ingredient. * @return The changed recipe, so you can chain calls. */ public ShapedRecipe setIngredient(char key, MaterialData ingredient) { return setIngredient(key, ingredient.getItemType(), ingredient.getData()); } /** * Sets the material that a character in the recipe shape refers to. * * @param key The character that represents the ingredient in the shape. * @param ingredient The ingredient. * @return The changed recipe, so you can chain calls. */ public ShapedRecipe setIngredient(char key, Material ingredient) { return setIngredient(key, ingredient, 0); } /** * Sets the material that a character in the recipe shape refers to. * * @param key The character that represents the ingredient in the shape. * @param ingredient The ingredient. * @param raw The raw material data as an integer. * @return The changed recipe, so you can chain calls. * @deprecated Magic value */ @Deprecated public ShapedRecipe setIngredient(char key, Material ingredient, int raw) { Validate.isTrue(ingredients.containsKey(key), "Symbol does not appear in the shape:", key); // -1 is the old wildcard, map to Short.MAX_VALUE as the new one if(raw == -1) { raw = Short.MAX_VALUE; } ingredients.put(key, new ItemStack(ingredient, 1, (short) raw)); return this; } /** * Get a copy of the ingredients map. * * @return The mapping of character to ingredients. */ public Map<Character, ItemStack> getIngredientMap() { HashMap<Character, ItemStack> result = new HashMap<Character, ItemStack>(); for(Map.Entry<Character, ItemStack> ingredient : ingredients.entrySet()) { if(ingredient.getValue() == null) { result.put(ingredient.getKey(), null); } else { result.put(ingredient.getKey(), ingredient.getValue().clone()); } } return result; } /** * Get the shape. * * @return The recipe's shape. */ public String[] getShape() { return rows.clone(); } /** * Get the result. * * @return The result stack. */ public ItemStack getResult() { return output.clone(); } }