From 519b15891fbf578a7c50ec274f7b525cee97ed14 Mon Sep 17 00:00:00 2001 From: James Peters Date: Wed, 2 Feb 2022 23:21:54 +0000 Subject: [PATCH] Fixed recipe issue Recipes with different amount of choices in the matrix caused a crash. i.e TNT. --- .../interfaces/VirtualCraftingHolder.java | 167 ++++++++---------- .../minecraft/chests/misc/Utils.java | 14 ++ 2 files changed, 84 insertions(+), 97 deletions(-) diff --git a/ChestsPlusPlus_Main/src/main/java/com/jamesdpeters/minecraft/chests/interfaces/VirtualCraftingHolder.java b/ChestsPlusPlus_Main/src/main/java/com/jamesdpeters/minecraft/chests/interfaces/VirtualCraftingHolder.java index e42adc2..ea7bd34 100644 --- a/ChestsPlusPlus_Main/src/main/java/com/jamesdpeters/minecraft/chests/interfaces/VirtualCraftingHolder.java +++ b/ChestsPlusPlus_Main/src/main/java/com/jamesdpeters/minecraft/chests/interfaces/VirtualCraftingHolder.java @@ -33,6 +33,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; public class VirtualCraftingHolder implements InventoryHolder { @@ -42,7 +43,8 @@ public class VirtualCraftingHolder implements InventoryHolder { private BukkitRunnable guiTask; private BukkitRunnable craftItemTask; - private ItemStack[][] recipeChoices = new ItemStack[9][]; + private RecipeChoice[] recipeChoices = new RecipeChoice[9]; + private Map> recipeChoiceItems = new HashMap<>(); private ItemStack result; private final int[] recipeChoiceIndex = new int[9]; private boolean hasCompleteRecipe = false; @@ -71,29 +73,19 @@ public class VirtualCraftingHolder implements InventoryHolder { public void setCrafting(ShapelessRecipe shapelessRecipe) { result = shapelessRecipe.getResult(); - List choiceList = shapelessRecipe.getChoiceList(); - for (int i = 0; i < choiceList.size(); i++) { - RecipeChoice recipeChoice = choiceList.get(i); - if (recipeChoice instanceof RecipeChoice.MaterialChoice materialChoice) { - ItemStack[] choices = materialChoice.getChoices().stream().map(ItemStack::new).toArray(ItemStack[]::new); - recipeChoices[i] = choices; - } - } + recipeChoices = shapelessRecipe.getChoiceList().toArray(new RecipeChoice[0]); setHasCompleteRecipe(); } public void setCrafting(ShapedRecipe recipe) { result = recipe.getResult(); + recipeChoices = new RecipeChoice[9]; int row = 0; for (String r : recipe.getShape()) { int col = 0; for (char c : r.toCharArray()) { - RecipeChoice recipeChoice = recipe.getChoiceMap().get(c); - if (recipeChoice instanceof RecipeChoice.MaterialChoice materialChoice) { - ItemStack[] choices = materialChoice.getChoices().stream().map(ItemStack::new).toArray(ItemStack[]::new); - int i = (row * 3) + col; - recipeChoices[i] = choices; - } + int i = (row * 3) + col; + recipeChoices[i] = recipe.getChoiceMap().get(c); col++; } row++; @@ -107,13 +99,14 @@ public class VirtualCraftingHolder implements InventoryHolder { else { // For ComplexRecipes or other implementations just use the result and original matrix for choices. result = ApiSpecific.getNmsProvider().getCraftingProvider().craft(Bukkit.getWorlds().get(0), matrix).result(); + recipeChoices = new RecipeChoice[9]; for (int i = 0; i < matrix.length; i++) { - ItemStack item = matrix[i]; + var item = matrix[i]; + RecipeChoice recipeChoice = null; if (item != null) { - recipeChoices[i] = new ItemStack[]{item}; - } else { - recipeChoices[i] = null; + recipeChoice = new RecipeChoice.MaterialChoice(item.getType()); } + recipeChoices[i] = recipeChoice; } setHasCompleteRecipe(); } @@ -121,11 +114,16 @@ public class VirtualCraftingHolder implements InventoryHolder { private void setHasCompleteRecipe() { hasCompleteRecipe = true; + for (RecipeChoice recipeChoice : recipeChoices) { + if (recipeChoice != null) + recipeChoiceItems.put(recipeChoice, Utils.getItemsFromRecipeChoice(recipeChoice)); + } startCraftingItems(); } public void resetChoices() { - recipeChoices = new ItemStack[9][]; + recipeChoices = new RecipeChoice[9]; + recipeChoiceItems.clear(); result = null; hasCompleteRecipe = false; stopCraftingItems(); @@ -174,7 +172,7 @@ public class VirtualCraftingHolder implements InventoryHolder { BukkitTask task; public UpdateTask() { - task = runTaskTimer(ChestsPlusPlus.PLUGIN, 1, 15); + task = runTaskTimer(ChestsPlusPlus.PLUGIN, 1, 30); } @Override @@ -187,20 +185,27 @@ public class VirtualCraftingHolder implements InventoryHolder { inventory.setItem(0, result); if (hasCompleteRecipe && !isUpdatingRecipe) { for (int i = 0; i < 9; i++) { - ItemStack[] choices = recipeChoices[i]; - if (choices != null) { - int index = recipeChoiceIndex[i]; + int index = recipeChoiceIndex[i]; + List choices = null; + + if (index < recipeChoices.length) { + var recipeChoice = recipeChoices[i]; + choices = recipeChoiceItems.get(recipeChoice); + } + + if (choices != null && !choices.isEmpty()) { ItemStack choice; - if (index < choices.length) { - choice = choices[index]; + if (index < choices.size()) { + choice = choices.get(index); } else { recipeChoiceIndex[i] = 0; - choice = choices[0]; + choice = choices.get(0); } inventory.setItem(i + 1, choice); recipeChoiceIndex[i]++; } else { inventory.setItem(i + 1, null); + recipeChoiceIndex[i] = 0; } } } @@ -292,16 +297,6 @@ public class VirtualCraftingHolder implements InventoryHolder { return inventory; } - private int getRecipeChoiceAmount() { - int max = 0; - for (ItemStack[] recipeChoice : recipeChoices) { - if (recipeChoice != null && recipeChoice.length > max){ - max = recipeChoice.length; - } - } - return max; - } - /** * Finds a valid recipe matrix for the currently selected recipe. * Removes the items from the inventories provided. @@ -309,81 +304,59 @@ public class VirtualCraftingHolder implements InventoryHolder { * @return a valid recipe matrix selected from the inventories provided. */ private ItemStack[] getRecipeMatrix(List inventories) { + // Store each item selected for the recipe. + // This is used to retrieve the actual result taking into account meta data, such as repairing items. + ItemStack[] tempRecipe = Utils.createAirList(9); - // Loop through recipe choice array to find recipeChoice index. - int recipeChoicesAmount = getRecipeChoiceAmount(); + // Need a new copy of the inventories to test for each recipe choice. + List tempInvs = Utils.copyInventoryList(inventories); - for (int recipeChoiceIndex = 0; recipeChoiceIndex < recipeChoicesAmount; recipeChoiceIndex++) { + for (int i = 0; i < recipeChoices.length; i++) { + var recipeChoice = recipeChoices[i]; + var possibleItems = recipeChoiceItems.get(recipeChoice); - // Store each item selected for the recipe. - // This is used to retrieve the actual result taking into account meta data, such as repairing items. - ItemStack[] tempRecipe = Utils.createAirList(9); - int recipeIndex = 0; + if (possibleItems == null) + continue; - // Need a new copy of the inventories to test for each recipe choice. - List tempInvs = Utils.copyInventoryList(inventories); + boolean foundMatch = false; + for (ItemStack possibleItem : possibleItems) { -// Bukkit.broadcastMessage("Recipe choices in loop: "+ Arrays.deepToString(recipeChoices)); + for (Inventory tempInv : tempInvs) { + int index = tempInv.first(possibleItem.getType()); - // Loops over each slot of the matrix - for (ItemStack[] choices : recipeChoices) { + if (index != -1) { + ItemStack item = tempInv.getItem(index); - // If there's no recipe choice at this index skip and set the matrix pos to null - if (choices == null){ - tempRecipe[recipeIndex] = null; - recipeIndex++; + if (item != null) { + // If a valid item has been found in one of the inventories. + ItemStack selectedItem = item.clone(); + item.setAmount(item.getAmount() - 1); + tempInv.setItem(index, item); - } else { // Otherwise check for a valid item for this recipe choice. - - // Select the current recipeChoice - ItemStack choice = choices[recipeChoiceIndex]; - - boolean foundMatch = false; - for (Inventory tempInv : tempInvs) { - int index = tempInv.first(choice.getType()); - - if (index != -1) { - ItemStack item = tempInv.getItem(index); - - if (item != null) { - // If a valid item has been found in one of the inventories. - ItemStack selectedItem = item.clone(); - -// if (selectedItem.getType()) - item.setAmount(item.getAmount() - 1); - tempInv.setItem(index, item); - - selectedItem.setAmount(1); - tempRecipe[recipeIndex] = selectedItem; - - recipeIndex++; - foundMatch = true; - break; - } + selectedItem.setAmount(1); + tempRecipe[i] = selectedItem; + foundMatch = true; + break; } } - - //If no match found - if (!foundMatch) { - break; - } - } - - // Completed the matrix - if ((recipeIndex >= recipeChoices.length)) { - - // Move temp invs to input invs. - for (int i = 0; i < tempInvs.size(); i++) { - moveTempInv(tempInvs.get(i), inventories.get(i)); - } - - return tempRecipe; } + if (foundMatch) + break; } + //If no match found + if (!foundMatch) { + return null; + } } - return null; + + // Move temp invs to input invs. + for (int i = 0; i < tempInvs.size(); i++) { + moveTempInv(tempInvs.get(i), inventories.get(i)); + } + + return tempRecipe; } private boolean craftItem(List inputs, Inventory output, Inventory craftingInventory) { diff --git a/ChestsPlusPlus_Main/src/main/java/com/jamesdpeters/minecraft/chests/misc/Utils.java b/ChestsPlusPlus_Main/src/main/java/com/jamesdpeters/minecraft/chests/misc/Utils.java index 2ecf726..ed1f2b6 100644 --- a/ChestsPlusPlus_Main/src/main/java/com/jamesdpeters/minecraft/chests/misc/Utils.java +++ b/ChestsPlusPlus_Main/src/main/java/com/jamesdpeters/minecraft/chests/misc/Utils.java @@ -24,6 +24,7 @@ import org.bukkit.entity.Player; import org.bukkit.event.inventory.InventoryType; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.RecipeChoice; import org.bukkit.util.Vector; import java.io.File; @@ -296,4 +297,17 @@ public class Utils { } return list; } + + public static List getItemsFromRecipeChoice(RecipeChoice recipeChoice) { + if (recipeChoice instanceof RecipeChoice.MaterialChoice materialChoice) { + return materialChoice.getChoices().stream().map(ItemStack::new).toList(); + } + else if (recipeChoice instanceof RecipeChoice.ExactChoice exactChoice) { + return exactChoice.getChoices(); + } + else { + return List.of(recipeChoice.getItemStack()); + } + + } }