From ad5211340aa224065da979ec77f8c3cf4a3c34ae Mon Sep 17 00:00:00 2001 From: BenWoodworth Date: Wed, 30 Mar 2016 02:47:08 -0400 Subject: [PATCH] Recipes in GUI don't show up if they can't actually be crafted. Call CraftItemEvent when an item is crafted. --- pom.xml | 2 +- .../co/kepler/fastcraftplus/FastCraft.java | 6 +- .../kepler/fastcraftplus/config/Recipes.java | 2 +- .../craftgui/GUIButtonRecipe.java | 20 +- .../fastcraftplus/craftgui/GUIFastCraft.java | 66 ++++- .../fastcraftplus/craftgui/LayoutRecipes.java | 2 +- .../crafting/CraftingInvWrapper.java | 253 ++++++++++++++++++ .../crafting/FCShapedRecipe.java | 22 +- .../crafting/FCShapelessRecipe.java | 13 +- .../fastcraftplus/crafting/GUIRecipe.java | 126 +++++++-- .../fastcraftplus/crafting/RecipeUtil.java | 3 +- src/main/resources/recipes.yml | 2 +- 12 files changed, 456 insertions(+), 61 deletions(-) create mode 100644 src/main/java/co/kepler/fastcraftplus/crafting/CraftingInvWrapper.java diff --git a/pom.xml b/pom.xml index a31f5551..91e6989e 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ co.kepler.fastcraftplus fastcraftplus - 0.3 + 0.4 diff --git a/src/main/java/co/kepler/fastcraftplus/FastCraft.java b/src/main/java/co/kepler/fastcraftplus/FastCraft.java index a31bfa06..420700a5 100644 --- a/src/main/java/co/kepler/fastcraftplus/FastCraft.java +++ b/src/main/java/co/kepler/fastcraftplus/FastCraft.java @@ -7,13 +7,12 @@ import co.kepler.fastcraftplus.craftgui.GUIFastCraft; import co.kepler.fastcraftplus.crafting.CraftingListener; import org.bukkit.Bukkit; -import org.bukkit.event.Listener; import org.bukkit.plugin.PluginManager; import org.bukkit.plugin.java.JavaPlugin; import java.util.logging.Level; -public class FastCraft extends JavaPlugin implements Listener { +public class FastCraft extends JavaPlugin { private static FastCraft instance; private Config config; @@ -74,8 +73,7 @@ public void onEnable() { PluginManager pluginManager = Bukkit.getPluginManager(); pluginManager.registerEvents(new CraftingListener(), this); - - GUIFastCraft.init(); + pluginManager.registerEvents(new GUIFastCraft.GUIListener(), this); } @Override diff --git a/src/main/java/co/kepler/fastcraftplus/config/Recipes.java b/src/main/java/co/kepler/fastcraftplus/config/Recipes.java index 43b3635d..475ad77f 100644 --- a/src/main/java/co/kepler/fastcraftplus/config/Recipes.java +++ b/src/main/java/co/kepler/fastcraftplus/config/Recipes.java @@ -34,7 +34,7 @@ public static void loadRecipes() { // Remove loaded recipes for (FCRecipe fcRecipe : recipes) { - for (Iterator iter = Bukkit.recipeIterator(); iter.hasNext();) { + for (Iterator iter = Bukkit.recipeIterator(); iter.hasNext(); ) { Recipe recipe = iter.next(); if (RecipeUtil.areEqual(recipe, fcRecipe.getRecipe())) { iter.remove(); diff --git a/src/main/java/co/kepler/fastcraftplus/craftgui/GUIButtonRecipe.java b/src/main/java/co/kepler/fastcraftplus/craftgui/GUIButtonRecipe.java index 0b2e0a08..4435ff8b 100644 --- a/src/main/java/co/kepler/fastcraftplus/craftgui/GUIButtonRecipe.java +++ b/src/main/java/co/kepler/fastcraftplus/craftgui/GUIButtonRecipe.java @@ -36,9 +36,12 @@ public GUIButtonRecipe(GUIFastCraft gui, GUIRecipe recipe) { super(); this.gui = gui; this.recipe = recipe; + } + @Override + public ItemStack getItem() { // Add the ingredients to the lore of the item - ItemStack item = recipe.getResult().clone(); + ItemStack item = recipe.getCraftingResult(gui).clone(); ItemMeta meta = item.getItemMeta(); LinkedList lore = new LinkedList<>(); Map ingredients = recipe.getIngredients(); @@ -58,8 +61,8 @@ public GUIButtonRecipe(GUIFastCraft gui, GUIRecipe recipe) { meta.setLore(lore); item.setItemMeta(meta); - // Set the item - setItem(item); + // Return the item + return item; } /** @@ -79,7 +82,7 @@ public void setClickAction(ClickAction clickAction) { */ @Override public boolean isVisible() { - return recipe.canCraft(gui.getPlayer(), false); + return recipe.canCraft(gui); } /** @@ -101,7 +104,9 @@ public void setVisible(boolean visible) { @Override public boolean onClick(Layout layout, InventoryClickEvent invEvent) { if (ignoreClicks.contains(invEvent.getClick())) return false; - if (!recipe.canCraft(gui.getPlayer(), true)) { + + List results = new ArrayList<>(); + if (!recipe.canCraft(gui, true, results)) { gui.updateLayout(); return false; } @@ -110,14 +115,15 @@ public boolean onClick(Layout layout, InventoryClickEvent invEvent) { case DROP: case CONTROL_DROP: // Drop items on the ground. - for (ItemStack is : recipe.getResults()) { + for (ItemStack is : results) { invEvent.getView().setItem(InventoryView.OUTSIDE, is); } break; default: // Add to inventory. Drop rest on ground if not enough space. Inventory inv = gui.getPlayer().getInventory(); - for (ItemStack is : inv.addItem(recipe.getResults()).values()) { + ItemStack[] resultsArr = new ItemStack[results.size()]; + for (ItemStack is : inv.addItem(results.toArray(resultsArr)).values()) { invEvent.getView().setItem(InventoryView.OUTSIDE, is); } break; diff --git a/src/main/java/co/kepler/fastcraftplus/craftgui/GUIFastCraft.java b/src/main/java/co/kepler/fastcraftplus/craftgui/GUIFastCraft.java index 4925706b..ed1febac 100644 --- a/src/main/java/co/kepler/fastcraftplus/craftgui/GUIFastCraft.java +++ b/src/main/java/co/kepler/fastcraftplus/craftgui/GUIFastCraft.java @@ -2,6 +2,7 @@ import co.kepler.fastcraftplus.FastCraft; import co.kepler.fastcraftplus.api.gui.*; +import co.kepler.fastcraftplus.crafting.CraftingInvWrapper; import org.bukkit.*; import org.bukkit.block.Block; import org.bukkit.entity.HumanEntity; @@ -16,9 +17,10 @@ import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryDragEvent; import org.bukkit.event.inventory.InventoryPickupItemEvent; +import org.bukkit.event.inventory.InventoryType; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerPickupItemEvent; -import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.*; import org.bukkit.inventory.meta.LeatherArmorMeta; import java.util.HashMap; @@ -31,12 +33,15 @@ public class GUIFastCraft extends GUI { private static final ChatColor BUTTON_NAME_COLOR = ChatColor.GREEN; private static final String NOT_YET_IMPLEMENTED = ChatColor.RED + "Not Yet Implemented"; - private static Map guis; // + private static Map guis = new HashMap<>(); // private final LayoutFastCraft craftLayout; private final Player player; private final Location location; + private final CraftingInvWrapper craftingInventory; + private final InventoryView craftingInventoryView; + private final GUIButton btnPagePrev; private final GUIButton btnPageNext; private final GUIButton btnRefresh; @@ -52,16 +57,39 @@ public class GUIFastCraft extends GUI { * @param player The player who will be shown this GUI. */ @SuppressWarnings("all") - public GUIFastCraft(Player player, Location location) { - super(FastCraft.lang().gui.title(), 6); // TODO Localize + public GUIFastCraft(final Player player, Location location) { + super(FastCraft.lang().gui.title(), 6); this.player = player; this.location = location; + craftingInventory = new CraftingInvWrapper(player); + craftingInventoryView = new InventoryView() { + @Override + public Inventory getTopInventory() { + return craftingInventory; + } + + @Override + public Inventory getBottomInventory() { + return player.getInventory(); + } + + @Override + public HumanEntity getPlayer() { + return player; + } + + @Override + public InventoryType getType() { + return craftingInventory.getType(); + } + }; + craftLayout = new LayoutFastCraft(this); setLayout(craftLayout); - // Create Previous Page button // TODO Localize + // Create Previous Page button btnPagePrev = new GUIButton(new GUIItemBuilder(Material.ARROW) .setDisplayName(FastCraft.lang().gui.toolbar.pagePrev.title()) .setLore(FastCraft.lang().gui.toolbar.pagePrev.description( @@ -185,11 +213,6 @@ public boolean onClick(GUIButton.Click info) { guis.put(location, this); } - public static void init() { - Bukkit.getPluginManager().registerEvents(new GUIListener(), FastCraft.getInstance()); - guis = new HashMap<>(); - } - @Override public void show(Player... players) { assert players.length == 1 && players[0].equals(player) : @@ -236,6 +259,27 @@ public Player getPlayer() { return player; } + /** + * Get this GUI's crafting inventory. + * + * @return Returns this GUI's crafting inventory. + */ + public CraftingInventory getCraftingInventory(Recipe recipe, ItemStack[] matrix, ItemStack result) { + craftingInventory.setRecipe(recipe); + craftingInventory.setMatrix(matrix); + craftingInventory.setResult(result); + return craftingInventory; + } + + /** + * Get this GUI's crafting inventory view. + * + * @return Returns this GUI's crafting inventory view. + */ + public InventoryView getCraftingInventoryView() { + return craftingInventoryView; + } + /** * Show a tab in the GUI. * @@ -274,7 +318,7 @@ private boolean btnCraftingMultiplierClick(GUIButton.Click info) { } private boolean btnWorkbenchClick(GUIButton.Click info) { - player.openWorkbench(location, true); // TODO Don't force + player.openWorkbench(location, false); return true; } diff --git a/src/main/java/co/kepler/fastcraftplus/craftgui/LayoutRecipes.java b/src/main/java/co/kepler/fastcraftplus/craftgui/LayoutRecipes.java index 69648fd5..1a010112 100644 --- a/src/main/java/co/kepler/fastcraftplus/craftgui/LayoutRecipes.java +++ b/src/main/java/co/kepler/fastcraftplus/craftgui/LayoutRecipes.java @@ -32,7 +32,7 @@ public LayoutRecipes(GUIFastCraft gui) { protected void addRecipes(List recipes) { for (GUIRecipe r : recipes) { // If the button is already in the gui, or if it can't be crafted, continue. - if (activeRecipes.contains(r) || !r.canCraft(gui.getPlayer(), false)) continue; + if (activeRecipes.contains(r) || !r.canCraft(gui)) continue; // Create the button, and add it to the GUI. GUIButtonRecipe button = new GUIButtonRecipe(gui, r); diff --git a/src/main/java/co/kepler/fastcraftplus/crafting/CraftingInvWrapper.java b/src/main/java/co/kepler/fastcraftplus/crafting/CraftingInvWrapper.java new file mode 100644 index 00000000..36e71440 --- /dev/null +++ b/src/main/java/co/kepler/fastcraftplus/crafting/CraftingInvWrapper.java @@ -0,0 +1,253 @@ +package co.kepler.fastcraftplus.crafting; + +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.entity.HumanEntity; +import org.bukkit.event.inventory.InventoryType; +import org.bukkit.inventory.*; + +import java.util.HashMap; +import java.util.List; +import java.util.ListIterator; + +/** + * A wrapper class for a CraftingInventory + */ +public class CraftingInvWrapper implements CraftingInventory { + private final Inventory craftingInv; + private Recipe recipe; + + /** + * Create a new instance of CraftingInvWrapper. + * + * @param owner The owner of the crafting inventory. + */ + public CraftingInvWrapper(InventoryHolder owner) { + craftingInv = Bukkit.createInventory(owner, InventoryType.WORKBENCH); + } + + @Override + public ItemStack getResult() { + return craftingInv.getItem(0); + } + + @Override + public void setResult(ItemStack itemStack) { + craftingInv.setItem(0, itemStack); + } + + @Override + public ItemStack[] getMatrix() { + ItemStack[] matrix = new ItemStack[9]; + System.arraycopy(getContents(), 1, matrix, 0, matrix.length); + return matrix; + } + + @Override + public void setMatrix(ItemStack[] itemStacks) { + ItemStack[] contents = getContents(); + System.arraycopy(itemStacks, 0, contents, 1, itemStacks.length); + setContents(contents); + } + + @Override + public Recipe getRecipe() { + return recipe; + } + + /** + * Set this crafting inventory's recipe. + * + * @param recipe The crafting inventory's new recipe. + */ + public void setRecipe(Recipe recipe) { + this.recipe = recipe; + } + + @Override + public int getSize() { + return craftingInv.getSize(); + } + + @Override + public int getMaxStackSize() { + return craftingInv.getMaxStackSize(); + } + + @Override + public void setMaxStackSize(int i) { + craftingInv.setMaxStackSize(i); + } + + @Override + public String getName() { + return craftingInv.getName(); + } + + @Override + public ItemStack getItem(int i) { + return craftingInv.getItem(i); + } + + @Override + public void setItem(int i, ItemStack itemStack) { + craftingInv.setItem(i, itemStack); + } + + @Override + public HashMap addItem(ItemStack... itemStacks) throws IllegalArgumentException { + return craftingInv.addItem(itemStacks); + } + + @Override + public HashMap removeItem(ItemStack... itemStacks) throws IllegalArgumentException { + return craftingInv.removeItem(itemStacks); + } + + @Override + public ItemStack[] getContents() { + return craftingInv.getContents(); + } + + @Override + public void setContents(ItemStack[] itemStacks) throws IllegalArgumentException { + craftingInv.setContents(itemStacks); + } + + @Override + @Deprecated + @SuppressWarnings("deprecation") + public boolean contains(int i) { + return craftingInv.contains(i); + } + + @Override + public boolean contains(Material material) throws IllegalArgumentException { + return craftingInv.contains(material); + } + + @Override + public boolean contains(ItemStack itemStack) { + return craftingInv.contains(itemStack); + } + + @Override + @Deprecated + @SuppressWarnings("deprecation") + public boolean contains(int i, int i1) { + return craftingInv.contains(i, i1); + } + + @Override + public boolean contains(Material material, int i) throws IllegalArgumentException { + return craftingInv.contains(material, i); + } + + @Override + public boolean contains(ItemStack itemStack, int i) { + return craftingInv.contains(itemStack, i); + } + + @Override + public boolean containsAtLeast(ItemStack itemStack, int i) { + return craftingInv.containsAtLeast(itemStack, i); + } + + @Override + @Deprecated + @SuppressWarnings("deprecation") + public HashMap all(int i) { + return craftingInv.all(i); + } + + @Override + public HashMap all(Material material) throws IllegalArgumentException { + return craftingInv.all(material); + } + + @Override + public HashMap all(ItemStack itemStack) { + return craftingInv.all(itemStack); + } + + @Override + @Deprecated + @SuppressWarnings("deprecation") + public int first(int i) { + return craftingInv.first(i); + } + + @Override + public int first(Material material) throws IllegalArgumentException { + return craftingInv.first(material); + } + + @Override + public int first(ItemStack itemStack) { + return craftingInv.first(itemStack); + } + + @Override + public int firstEmpty() { + return craftingInv.firstEmpty(); + } + + @Override + @Deprecated + @SuppressWarnings("deprecation") + public void remove(int i) { + craftingInv.remove(i); + } + + @Override + public void remove(Material material) throws IllegalArgumentException { + craftingInv.remove(material); + } + + @Override + public void remove(ItemStack itemStack) { + craftingInv.remove(itemStack); + } + + @Override + @Deprecated + @SuppressWarnings("deprecation") + public void clear(int i) { + craftingInv.remove(i); + } + + @Override + public void clear() { + craftingInv.clear(); + } + + @Override + public List getViewers() { + return craftingInv.getViewers(); + } + + @Override + public String getTitle() { + return craftingInv.getTitle(); + } + + @Override + public InventoryType getType() { + return craftingInv.getType(); + } + + @Override + public InventoryHolder getHolder() { + return craftingInv.getHolder(); + } + + @Override + public ListIterator iterator() { + return craftingInv.iterator(); + } + + @Override + public ListIterator iterator(int i) { + return craftingInv.iterator(i); + } +} diff --git a/src/main/java/co/kepler/fastcraftplus/crafting/FCShapedRecipe.java b/src/main/java/co/kepler/fastcraftplus/crafting/FCShapedRecipe.java index 948a2e6e..c4db38bb 100644 --- a/src/main/java/co/kepler/fastcraftplus/crafting/FCShapedRecipe.java +++ b/src/main/java/co/kepler/fastcraftplus/crafting/FCShapedRecipe.java @@ -62,8 +62,17 @@ public FCShapedRecipe(ItemStack result, Map ingredientsMa recipe.setIngredient(key, ingredientsMap.get(key).getMaterialData()); } + // Create matrix + ItemStack[] matrix = new ItemStack[9]; + for (int row = 0; row < shapeArr.length; row++) { + char[] chars = shapeArr[row].toCharArray(); + for (int col = 0; col < chars.length; col++) { + matrix[row * 3 + col] = ingredientsMap.get(chars[col]).toItemStack(1); + } + } + // Create GUIRecipe - guiRecipe = new GUIRecipe(ingredients, result); + guiRecipe = new GUIRecipe(ingredients, recipe, result, matrix); } @Override @@ -87,7 +96,8 @@ public boolean matchesMatrix(ItemStack[] matrix) { ItemStack[] matrixFlip = new ItemStack[matrix.length]; for (int x = 0; x < 3; x++) { for (int y = 0; y < 3; y++) { - if (matrix[x + (y * 3)].getType() == Material.AIR) { + ItemStack curItem = matrix[x + (y * 3)]; + if (curItem != null && curItem.getType() == Material.AIR) { matrix[x + (y * 3)] = null; } matrixFlip[(2 - x) + (y * 3)] = matrix[x + (y * 3)]; @@ -114,12 +124,12 @@ public boolean matchesMatrix(ItemStack[] matrix) { */ private boolean matchesMatrix(ItemStack[] matrix, int dx, int dy) { // Compare ingredients with items in the matrix - for (int row = 0; row < rows; row++) { - for (int col = 0; col < cols; col++) { + for (int row = 0; row < 3; row++) { + for (int col = 0; col < 3; col++) { ItemStack item = matrix[row * 3 + col]; - if (row < dy || col < dx || row > dy + rows || col > dx + cols) { + if (row < dy || col < dx || row >= dy + rows || col >= dx + cols) { // If outside the current recipe - if (item != null) return false; + if (item != null && item.getType() != Material.AIR) return false; } else { // If inside the current recipe Ingredient ingredient = ingredientGrid[row - dy][col - dx]; diff --git a/src/main/java/co/kepler/fastcraftplus/crafting/FCShapelessRecipe.java b/src/main/java/co/kepler/fastcraftplus/crafting/FCShapelessRecipe.java index 114609f5..1dacbc0e 100644 --- a/src/main/java/co/kepler/fastcraftplus/crafting/FCShapelessRecipe.java +++ b/src/main/java/co/kepler/fastcraftplus/crafting/FCShapelessRecipe.java @@ -34,13 +34,22 @@ public FCShapelessRecipe(ItemStack result, Map ingredients) } // Create Recipe + ItemStack[] matrix = new ItemStack[9]; + int matIndex = 0; recipe = new ShapelessRecipe(result); for (Ingredient ingredient : ingredients.keySet()) { - recipe.addIngredient(ingredients.get(ingredient), ingredient.getMaterialData()); // TODO Ignoring item data + int amount = ingredients.get(ingredient); + recipe.addIngredient(amount, ingredient.getMaterialData()); + + // Add items to matrix + ItemStack matItem = ingredient.toItemStack(1); + for (int i = 0; i < amount; i++) { + matrix[matIndex++] = matItem; + } } // Create GUIRecipe - guiRecipe = new GUIRecipe(ingredients, result); + guiRecipe = new GUIRecipe(ingredients, recipe, result, matrix); } @Override diff --git a/src/main/java/co/kepler/fastcraftplus/crafting/GUIRecipe.java b/src/main/java/co/kepler/fastcraftplus/crafting/GUIRecipe.java index 9d91ec0c..aca09cf5 100644 --- a/src/main/java/co/kepler/fastcraftplus/crafting/GUIRecipe.java +++ b/src/main/java/co/kepler/fastcraftplus/crafting/GUIRecipe.java @@ -1,20 +1,26 @@ package co.kepler.fastcraftplus.crafting; +import co.kepler.fastcraftplus.craftgui.GUIFastCraft; +import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; -import org.bukkit.inventory.Recipe; -import org.bukkit.inventory.ShapedRecipe; -import org.bukkit.inventory.ShapelessRecipe; +import org.bukkit.event.Event; +import org.bukkit.event.inventory.*; +import org.bukkit.inventory.*; -import java.util.*; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; /** * Holds the ingredients and result of a recipe. */ public class GUIRecipe implements Comparable { private Map ingredients; + private Recipe recipe; private ItemStack result; + private ItemStack[] matrix; /** * Create a recipe from ingredients, a result, and byproducts. @@ -22,9 +28,11 @@ public class GUIRecipe implements Comparable { * @param ingredients The ingredients used to craft this recipe. * @param result The result of this recipe. */ - public GUIRecipe(Map ingredients, ItemStack result) { + public GUIRecipe(Map ingredients, Recipe recipe, ItemStack result, ItemStack[] matrix) { this.ingredients = ingredients; + this.recipe = recipe; this.result = result; + this.matrix = matrix; } /** @@ -36,26 +44,45 @@ public GUIRecipe(Recipe recipe) { assert canBeGUIRecipe(recipe) : "Recipe must be a shaped or shapeless recipe"; ingredients = new HashMap<>(); + this.recipe = recipe; result = recipe.getResult(); // Get ingredients from recipe + matrix = new ItemStack[9]; + int matIndex = 0; if (recipe instanceof ShapedRecipe) { ShapedRecipe r = (ShapedRecipe) recipe; for (String str : r.getShape()) { + int matRow = 0; for (char c : str.toCharArray()) { + // Add ingredients to the ingredients map ItemStack is = r.getIngredientMap().get(c); if (is == null) continue; Ingredient i = new Ingredient(is); - Integer old = ingredients.get(i); - ingredients.put(i, (old == null ? 0 : old) + 1); + Integer amount = ingredients.get(i); + ingredients.put(i, (amount == null ? 0 : amount) + 1); + + ItemStack matItem = is.clone(); + matItem.setAmount(1); + matrix[matIndex + matRow] = matItem; } + matIndex += 3; } } else if (recipe instanceof ShapelessRecipe) { ShapelessRecipe r = (ShapelessRecipe) recipe; for (ItemStack is : r.getIngredientList()) { - Ingredient i = new Ingredient(is); - Integer old = ingredients.get(i); - ingredients.put(i, (old == null ? 0 : old) + 1); + // Add ingredient to the ingredients map + Ingredient ingredient = new Ingredient(is); + Integer amount = ingredients.get(ingredient); + amount = (amount == null ? 0 : amount) + 1; + ingredients.put(ingredient, amount); + + // Add items to the matrix + ItemStack matItem = is.clone(); + matItem.setAmount(1); + for (int i = 0; i < amount; i++) { + matrix[matIndex++] = matItem; + } } } } @@ -79,28 +106,37 @@ public ItemStack getResult() { return result; } + /** + * Get the result from crafting this recipe in a crafting grid. + * + * @param gui The GUI containing this recipe. + * @return Returns the result from crafting this recipe in a crafting grid. + */ + public ItemStack getCraftingResult(GUIFastCraft gui) { + CraftingInventory inv = gui.getCraftingInventory(recipe, matrix, result); + PrepareItemCraftEvent prepareEvent = new PrepareItemCraftEvent(inv, gui.getCraftingInventoryView(), false); + Bukkit.getPluginManager().callEvent(prepareEvent); + return prepareEvent.getInventory().getResult(); + } + /** * Gets all the results of this recipe, including byproducts * like empty buckets from recipes that require filled buckets. * - * @return Return the results of this recipe. + * @param craftingResult The result from crafting in a crafting table. + * @param results The list to populate with crafting results. */ - public ItemStack[] getResults() { - List byproducts = new ArrayList<>(); + private void getResults(ItemStack craftingResult, List results) { + results.clear(); + results.add(craftingResult); for (Ingredient i : ingredients.keySet()) { switch (i.getMaterial()) { case LAVA_BUCKET: case MILK_BUCKET: case WATER_BUCKET: - byproducts.add(new ItemStack(Material.BUCKET, ingredients.get(i))); + results.add(new ItemStack(Material.BUCKET, ingredients.get(i))); } } - ItemStack[] results = new ItemStack[byproducts.size() + 1]; - results[0] = result.clone(); - for (int i = 0; i < byproducts.size(); i++) { - results[i + 1] = byproducts.get(i); - } - return results; } /** @@ -113,6 +149,19 @@ public Map getIngredients() { return ingredients; } + /** + * Get the matrix of items in a crafting grid for this recipe. + * + * @return Returns the recipe's matrix. + */ + public ItemStack[] getMatrix() { + ItemStack[] copy = new ItemStack[matrix.length]; + for (int i = 0; i < copy.length; i++) { + copy[i] = matrix[i] == null ? null : matrix[i].clone(); + } + return copy; + } + /** * Remove ingredients from an inventory. * @@ -146,11 +195,16 @@ public boolean removeIngredients(ItemStack[] items) { * See if a player has this recipe's ingredients, and optionally, remove them * from the player's inventory if all ingredients are present. * - * @param player The player whose inventory will have ingredients removed. - * @param remove Whether ingredients should be removed if all exist in the player's inventory. + * @param gui The GUI this recipe is being crafted in. + * @param craft Whether this recipe should be crafted if the player has all the ingredients. * @return Returns true if the ingredients were removed from the player's inventory. */ - public boolean canCraft(Player player, boolean remove) { + public boolean canCraft(GUIFastCraft gui, boolean craft, List results) { + Player player = gui.getPlayer(); + ItemStack craftingResult = getCraftingResult(gui); + if (craftingResult == null || craftingResult.getType() == Material.AIR) return false; + + // Clone the items in the player's inventory ItemStack[] contents = player.getInventory().getContents(); for (int i = 0; i < contents.length; i++) { if (contents[i] == null) continue; @@ -158,13 +212,33 @@ public boolean canCraft(Player player, boolean remove) { } boolean allRemoved = removeIngredients(contents); - if (allRemoved && remove) { + if (allRemoved && craft) { + // Call crafting event. Cancel crafting if event is cancelled. + CraftItemEvent craftEvent = new CraftItemEvent(recipe, gui.getCraftingInventoryView(), + InventoryType.SlotType.RESULT, 0, ClickType.LEFT, InventoryAction.PICKUP_ONE); + Bukkit.getPluginManager().callEvent(craftEvent); + if (craftEvent.isCancelled() || craftEvent.getResult() == Event.Result.DENY) return false; + + // Update inventory to reflect removed items player.getInventory().setContents(contents); - RecipeUtil.getInstance().awardAchievement(player, result); + getResults(craftingResult, results); + + // Award achievement + RecipeUtil.getInstance().awardAchievement(player, craftingResult); } return allRemoved; } + /** + * See if a player has this recipe's ingredients, and optionally, remove them + * from the player's inventory if all ingredients are present. + * + * @param gui The GUI this recipe is being crafted in. + */ + public boolean canCraft(GUIFastCraft gui) { + return canCraft(gui, false, null); + } + @Override @SuppressWarnings("deprecation") public int compareTo(GUIRecipe compareTo) { diff --git a/src/main/java/co/kepler/fastcraftplus/crafting/RecipeUtil.java b/src/main/java/co/kepler/fastcraftplus/crafting/RecipeUtil.java index 155343a2..d5e0efb2 100644 --- a/src/main/java/co/kepler/fastcraftplus/crafting/RecipeUtil.java +++ b/src/main/java/co/kepler/fastcraftplus/crafting/RecipeUtil.java @@ -222,7 +222,8 @@ public String getItemName(ItemStack item) { } catch (IllegalAccessException | InvocationTargetException e) { e.printStackTrace(); } - new Exception("getItemName() can't find name").printStackTrace(); // TODO Remove + + new Exception("Can't find name of ItemStack: " + item).printStackTrace(); return "ERROR"; } diff --git a/src/main/resources/recipes.yml b/src/main/resources/recipes.yml index 911c7e0f..ff024ced 100644 --- a/src/main/resources/recipes.yml +++ b/src/main/resources/recipes.yml @@ -33,7 +33,7 @@ # thick_sword: # type: shaped # ingredients: -# p: ['minecraft:planks', ANY] +# p: ['minecraft:planks', ANY, '{display:{Name:"Thick Stick"}}'] # d: ['minecraft:diamond_block'] # shape: # - 'd'