mirror of
https://github.com/PaperMC/Paper.git
synced 2025-01-23 08:41:27 +01:00
[Bleeding] Add ways to retrieve and delete crafting recipes and fixed some issues with the existing recipe API.
- New recipe iterator which enables deleting specific recipes - Functions to delete all recipes or revert to vanilla recipe set - Fixed the recipes API; you should now be able to define recipes that take brewed potions! - Fetch all recipes that result in a specific item By: Celtic Minstrel <celtic.minstrel.ca@some.place>
This commit is contained in:
parent
8bc2cf4969
commit
07ccb2a000
@ -1,6 +1,7 @@
|
||||
package org.bukkit;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@ -11,6 +12,7 @@ import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
import org.bukkit.command.PluginCommand;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.Recipe;
|
||||
import org.bukkit.map.MapView;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
@ -192,6 +194,22 @@ public final class Bukkit {
|
||||
return server.addRecipe(recipe);
|
||||
}
|
||||
|
||||
public List<Recipe> getRecipesFor(ItemStack result) {
|
||||
return server.getRecipesFor(result);
|
||||
}
|
||||
|
||||
public Iterator<Recipe> recipeIterator() {
|
||||
return server.recipeIterator();
|
||||
}
|
||||
|
||||
public void clearRecipes() {
|
||||
server.clearRecipes();
|
||||
}
|
||||
|
||||
public void resetRecipes() {
|
||||
server.resetRecipes();
|
||||
}
|
||||
|
||||
public static Map<String, String[]> getCommandAliases() {
|
||||
return server.getCommandAliases();
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package org.bukkit;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@ -12,6 +13,7 @@ import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.command.ConsoleCommandSender;
|
||||
import org.bukkit.command.PluginCommand;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.Recipe;
|
||||
import org.bukkit.map.MapView;
|
||||
import org.bukkit.plugin.PluginManager;
|
||||
@ -382,10 +384,36 @@ public interface Server extends PluginMessageRecipient {
|
||||
* Adds a recipe to the crafting manager.
|
||||
*
|
||||
* @param recipe The recipe to add.
|
||||
* @return True to indicate that the recipe was added.
|
||||
* @return True if the recipe was added, false if it wasn't for some reason.
|
||||
*/
|
||||
public boolean addRecipe(Recipe recipe);
|
||||
|
||||
/**
|
||||
* Get a list of all recipes for a given item. The stack size is ignored in comparisons.
|
||||
* If the durability is -1, it will match any data value.
|
||||
*
|
||||
* @param result The item whose recipes you want
|
||||
* @return The list of recipes
|
||||
*/
|
||||
public List<Recipe> getRecipesFor(ItemStack result);
|
||||
|
||||
/**
|
||||
* Get an iterator through the list of crafting recipes.
|
||||
*
|
||||
* @return The iterator.
|
||||
*/
|
||||
public Iterator<Recipe> recipeIterator();
|
||||
|
||||
/**
|
||||
* Clears the list of crafting recipes.
|
||||
*/
|
||||
public void clearRecipes();
|
||||
|
||||
/**
|
||||
* Resets the list of crafting recipes to the default.
|
||||
*/
|
||||
public void resetRecipes();
|
||||
|
||||
/**
|
||||
* Gets a list of command aliases defined in the server properties.
|
||||
*
|
||||
|
@ -8,7 +8,7 @@ import org.bukkit.material.MaterialData;
|
||||
*/
|
||||
public class FurnaceRecipe implements Recipe {
|
||||
private ItemStack output;
|
||||
private MaterialData ingredient;
|
||||
private ItemStack ingredient;
|
||||
|
||||
/**
|
||||
* Create a furnace recipe to craft the specified ItemStack.
|
||||
@ -17,10 +17,7 @@ public class FurnaceRecipe implements Recipe {
|
||||
* @param source The input material.
|
||||
*/
|
||||
public FurnaceRecipe(ItemStack result, Material source) {
|
||||
this(result, source.getNewData((byte) 0));
|
||||
if (this.ingredient == null) {
|
||||
setInput(new MaterialData(source));
|
||||
}
|
||||
this(result, source, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -30,8 +27,19 @@ public class FurnaceRecipe implements Recipe {
|
||||
* @param source The input material.
|
||||
*/
|
||||
public FurnaceRecipe(ItemStack result, MaterialData source) {
|
||||
this.output = result;
|
||||
this.ingredient = source;
|
||||
this(result, source.getItemType(), source.getData());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a furnace recipe to craft the specified ItemStack.
|
||||
*
|
||||
* @param result The item you want the recipe to create.
|
||||
* @param source The input material.
|
||||
* @param data The data value. (Note: This is currently ignored by the CraftBukkit server.)
|
||||
*/
|
||||
public FurnaceRecipe(ItemStack result, Material source, int data) {
|
||||
this.output = new ItemStack(result);
|
||||
this.ingredient = new ItemStack(source, 1, (short) data);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -41,8 +49,7 @@ public class FurnaceRecipe implements Recipe {
|
||||
* @return The changed recipe, so you can chain calls.
|
||||
*/
|
||||
public FurnaceRecipe setInput(MaterialData input) {
|
||||
this.ingredient = input;
|
||||
return this;
|
||||
return setInput(input.getItemType(), input.getData());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -52,10 +59,18 @@ public class FurnaceRecipe implements Recipe {
|
||||
* @return The changed recipe, so you can chain calls.
|
||||
*/
|
||||
public FurnaceRecipe setInput(Material input) {
|
||||
setInput(input.getNewData((byte) 0));
|
||||
if (this.ingredient == null) {
|
||||
setInput(new MaterialData(input));
|
||||
}
|
||||
return setInput(input, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the input of this furnace recipe.
|
||||
*
|
||||
* @param input The input material.
|
||||
* @param data The data value. (Note: This is currently ignored by the CraftBukkit server.)
|
||||
* @return The changed recipe, so you can chain calls.
|
||||
*/
|
||||
public FurnaceRecipe setInput(Material input, int data) {
|
||||
this.ingredient = new ItemStack(input, 1, (short) data);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -64,8 +79,8 @@ public class FurnaceRecipe implements Recipe {
|
||||
*
|
||||
* @return The input material.
|
||||
*/
|
||||
public MaterialData getInput() {
|
||||
return ingredient;
|
||||
public ItemStack getInput() {
|
||||
return this.ingredient.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -74,6 +89,6 @@ public class FurnaceRecipe implements Recipe {
|
||||
* @return The resulting stack.
|
||||
*/
|
||||
public ItemStack getResult() {
|
||||
return output;
|
||||
return output.clone();
|
||||
}
|
||||
}
|
||||
|
@ -57,6 +57,16 @@ public class ItemStack implements Cloneable, ConfigurationSerializable {
|
||||
this(type.getId(), amount, damage, data);
|
||||
}
|
||||
|
||||
public ItemStack(final ItemStack stack) {
|
||||
this.type = stack.type;
|
||||
this.amount = stack.amount;
|
||||
this.durability = stack.durability;
|
||||
if (stack.data != null) {
|
||||
this.data = stack.data.clone();
|
||||
}
|
||||
enchantments.putAll(stack.enchantments);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type of this item
|
||||
*
|
||||
|
@ -1,6 +1,9 @@
|
||||
package org.bukkit.inventory;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.material.MaterialData;
|
||||
@ -11,7 +14,7 @@ import org.bukkit.material.MaterialData;
|
||||
public class ShapedRecipe implements Recipe {
|
||||
private ItemStack output;
|
||||
private String[] rows;
|
||||
private HashMap<Character, MaterialData> ingredients = new HashMap<Character, MaterialData>();
|
||||
private Map<Character, ItemStack> ingredients = new HashMap<Character, ItemStack>();
|
||||
|
||||
/**
|
||||
* Create a shaped recipe to craft the specified ItemStack. The constructor merely determines the
|
||||
@ -24,7 +27,7 @@ public class ShapedRecipe implements Recipe {
|
||||
* @see ShapedRecipe#setIngredient(char, MaterialData)
|
||||
*/
|
||||
public ShapedRecipe(ItemStack result) {
|
||||
this.output = result;
|
||||
this.output = new ItemStack(result);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -34,26 +37,28 @@ public class ShapedRecipe implements Recipe {
|
||||
* @param shape The rows of the recipe (up to 3 rows).
|
||||
* @return The changed recipe, so you can chain calls.
|
||||
*/
|
||||
public ShapedRecipe shape(String... shape) {
|
||||
if (shape == null || shape.length > 3 || shape.length < 1) {
|
||||
throw new IllegalArgumentException("Crafting recipes should be 1, 2, or 3 rows.");
|
||||
}
|
||||
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) {
|
||||
if (row == null || row.length() > 3 || row.length() < 1) {
|
||||
throw new IllegalArgumentException("Crafting rows should be 1, 2, or 3 characters.");
|
||||
}
|
||||
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];
|
||||
}
|
||||
this.rows = shape;
|
||||
|
||||
// Remove character mappings for characters that no longer exist in the shape
|
||||
HashMap<Character, MaterialData> ingredientsTemp = this.ingredients;
|
||||
|
||||
this.ingredients = new HashMap<Character, MaterialData>();
|
||||
for (char key : ingredientsTemp.keySet()) {
|
||||
try {
|
||||
setIngredient(key, ingredientsTemp.get(key));
|
||||
} catch (IllegalArgumentException e) {}
|
||||
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;
|
||||
}
|
||||
|
||||
@ -65,11 +70,7 @@ public class ShapedRecipe implements Recipe {
|
||||
* @return The changed recipe, so you can chain calls.
|
||||
*/
|
||||
public ShapedRecipe setIngredient(char key, MaterialData ingredient) {
|
||||
if (!hasKey(key)) {
|
||||
throw new IllegalArgumentException("Symbol " + key + " does not appear in the shape.");
|
||||
}
|
||||
ingredients.put(key, ingredient);
|
||||
return this;
|
||||
return setIngredient(key, ingredient.getItemType(), ingredient.getData());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -92,32 +93,26 @@ public class ShapedRecipe implements Recipe {
|
||||
* @return The changed recipe, so you can chain calls.
|
||||
*/
|
||||
public ShapedRecipe setIngredient(char key, Material ingredient, int raw) {
|
||||
MaterialData data = ingredient.getNewData((byte) raw);
|
||||
|
||||
if (data == null) {
|
||||
data = new MaterialData(ingredient, (byte) raw);
|
||||
}
|
||||
return setIngredient(key, data);
|
||||
}
|
||||
|
||||
private boolean hasKey(char c) {
|
||||
String key = Character.toString(c);
|
||||
|
||||
for (String row : rows) {
|
||||
if (row.contains(key)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
Validate.isTrue(ingredients.containsKey(key), "Symbol does not appear in the shape:", key);
|
||||
ingredients.put(key, new ItemStack(ingredient, 1, (short) raw));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ingredients map.
|
||||
* Get a copy of the ingredients map.
|
||||
*
|
||||
* @return The mapping of character to ingredients.
|
||||
*/
|
||||
public HashMap<Character, MaterialData> getIngredientMap() {
|
||||
return 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;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -126,7 +121,7 @@ public class ShapedRecipe implements Recipe {
|
||||
* @return The recipe's shape.
|
||||
*/
|
||||
public String[] getShape() {
|
||||
return rows;
|
||||
return rows.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -135,6 +130,6 @@ public class ShapedRecipe implements Recipe {
|
||||
* @return The result stack.
|
||||
*/
|
||||
public ItemStack getResult() {
|
||||
return output;
|
||||
return output.clone();
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,10 @@
|
||||
package org.bukkit.inventory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang.Validate;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.material.MaterialData;
|
||||
@ -11,7 +15,7 @@ import org.bukkit.material.MaterialData;
|
||||
*/
|
||||
public class ShapelessRecipe implements Recipe {
|
||||
private ItemStack output;
|
||||
private ArrayList<MaterialData> ingredients = new ArrayList<MaterialData>();
|
||||
private List<ItemStack> ingredients = new ArrayList<ItemStack>();
|
||||
|
||||
/**
|
||||
* Create a shapeless recipe to craft the specified ItemStack. The constructor merely determines the
|
||||
@ -20,9 +24,13 @@ public class ShapelessRecipe implements Recipe {
|
||||
* @param result The item you want the recipe to create.
|
||||
* @see ShapelessRecipe#addIngredient(Material)
|
||||
* @see ShapelessRecipe#addIngredient(MaterialData)
|
||||
* @see ShapelessRecipe#addIngredient(Material,int)
|
||||
* @see ShapelessRecipe#addIngredient(int,Material)
|
||||
* @see ShapelessRecipe#addIngredient(int,MaterialData)
|
||||
* @see ShapelessRecipe#addIngredient(int,Material,int)
|
||||
*/
|
||||
public ShapelessRecipe(ItemStack result) {
|
||||
this.output = result;
|
||||
this.output = new ItemStack(result);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -49,7 +57,7 @@ public class ShapelessRecipe implements Recipe {
|
||||
* Adds the specified ingredient.
|
||||
*
|
||||
* @param ingredient The ingredient to add.
|
||||
* @param rawdata The data value.
|
||||
* @param rawdata The data value, or -1 to allow any data value.
|
||||
* @return The changed recipe, so you can chain calls.
|
||||
*/
|
||||
public ShapelessRecipe addIngredient(Material ingredient, int rawdata) {
|
||||
@ -64,13 +72,7 @@ public class ShapelessRecipe implements Recipe {
|
||||
* @return The changed recipe, so you can chain calls.
|
||||
*/
|
||||
public ShapelessRecipe addIngredient(int count, MaterialData ingredient) {
|
||||
if (ingredients.size() + count > 9) {
|
||||
throw new IllegalArgumentException("Shapeless recipes cannot have more than 9 ingredients");
|
||||
}
|
||||
while (count-- > 0) {
|
||||
ingredients.add(ingredient);
|
||||
}
|
||||
return this;
|
||||
return addIngredient(count, ingredient.getItemType(), ingredient.getData());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -89,27 +91,100 @@ public class ShapelessRecipe implements Recipe {
|
||||
*
|
||||
* @param count How many to add (can't be more than 9!)
|
||||
* @param ingredient The ingredient to add.
|
||||
* @param rawdata The data value.
|
||||
* @param rawdata The data value, or -1 to allow any data value.
|
||||
* @return The changed recipe, so you can chain calls.
|
||||
*/
|
||||
public ShapelessRecipe addIngredient(int count, Material ingredient, int rawdata) {
|
||||
MaterialData data = ingredient.getNewData((byte) rawdata);
|
||||
Validate.isTrue(ingredients.size() + count <= 9, "Shapeless recipes cannot have more than 9 ingredients");
|
||||
|
||||
if (data == null) {
|
||||
data = new MaterialData(ingredient, (byte) rawdata);
|
||||
while (count-- > 0) {
|
||||
ingredients.add(new ItemStack(ingredient, 1, (short) rawdata));
|
||||
}
|
||||
return addIngredient(count, data);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an ingredient from the list. If the ingredient occurs multiple times,
|
||||
* only one instance of it is removed.
|
||||
* only one instance of it is removed. Only removes exact matches, with a data value
|
||||
* of 0.
|
||||
*
|
||||
* @param ingredient The ingredient to remove
|
||||
* @return The changed recipe.
|
||||
*/
|
||||
public ShapelessRecipe removeIngredient(Material ingredient) {
|
||||
return removeIngredient(ingredient, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an ingredient from the list. If the ingredient occurs multiple times,
|
||||
* only one instance of it is removed. If the data value is -1, only ingredients
|
||||
* with a -1 data value will be removed.
|
||||
*
|
||||
* @param ingredient The ingredient to remove
|
||||
* @return The changed recipe.
|
||||
*/
|
||||
public ShapelessRecipe removeIngredient(MaterialData ingredient) {
|
||||
this.ingredients.remove(ingredient);
|
||||
return removeIngredient(ingredient.getItemType(), ingredient.getData());
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes multiple instances of an ingredient from the list. If there are less instances
|
||||
* then specified, all will be removed. Only removes exact matches, with a data value
|
||||
* of 0.
|
||||
*
|
||||
* @param count The number of copies to remove.
|
||||
* @param ingredient The ingredient to remove
|
||||
* @return The changed recipe.
|
||||
*/
|
||||
public ShapelessRecipe removeIngredient(int count, Material ingredient) {
|
||||
return removeIngredient(count, ingredient, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes multiple instances of an ingredient from the list. If there are less instances
|
||||
* then specified, all will be removed. If the data value is -1, only ingredients
|
||||
* with a -1 data value will be removed.
|
||||
*
|
||||
* @param count The number of copies to remove.
|
||||
* @param ingredient The ingredient to remove.
|
||||
* @return The changed recipe.
|
||||
*/
|
||||
public ShapelessRecipe removeIngredient(int count, MaterialData ingredient) {
|
||||
return removeIngredient(count, ingredient.getItemType(), ingredient.getData());
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an ingredient from the list. If the ingredient occurs multiple times,
|
||||
* only one instance of it is removed. If the data value is -1, only ingredients
|
||||
* with a -1 data value will be removed.
|
||||
*
|
||||
* @param ingredient The ingredient to remove
|
||||
* @param rawdata The data value;
|
||||
* @return The changed recipe.
|
||||
*/
|
||||
public ShapelessRecipe removeIngredient(Material ingredient, int rawdata) {
|
||||
return removeIngredient(1, ingredient, rawdata);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes multiple instances of an ingredient from the list. If there are less instances
|
||||
* then specified, all will be removed. If the data value is -1, only ingredients
|
||||
* with a -1 data value will be removed.
|
||||
*
|
||||
* @param count The number of copies to remove.
|
||||
* @param ingredient The ingredient to remove.
|
||||
* @param rawdata The data value.
|
||||
* @return The changed recipe.
|
||||
*/
|
||||
public ShapelessRecipe removeIngredient(int count, Material ingredient, int rawdata) {
|
||||
Iterator<ItemStack> iterator = ingredients.iterator();
|
||||
while (count > 0 && iterator.hasNext()) {
|
||||
ItemStack stack = iterator.next();
|
||||
if (stack.getType() == ingredient && stack.getDurability() == rawdata) {
|
||||
iterator.remove();
|
||||
count--;
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -119,7 +194,7 @@ public class ShapelessRecipe implements Recipe {
|
||||
* @return The result stack.
|
||||
*/
|
||||
public ItemStack getResult() {
|
||||
return output;
|
||||
return output.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -127,7 +202,11 @@ public class ShapelessRecipe implements Recipe {
|
||||
*
|
||||
* @return The input list
|
||||
*/
|
||||
public ArrayList<MaterialData> getIngredientList() {
|
||||
return ingredients;
|
||||
public List<ItemStack> getIngredientList() {
|
||||
ArrayList<ItemStack> result = new ArrayList<ItemStack>(ingredients.size());
|
||||
for (ItemStack ingredient : ingredients) {
|
||||
result.add(ingredient.clone());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user