From a7f9e01d61f7ffbff80cccd8fe2d566c97846dd7 Mon Sep 17 00:00:00 2001 From: BONNe Date: Sun, 16 Jun 2019 15:57:05 +0300 Subject: [PATCH] Fix issue when unstackable items flood challenge description (#135) --- .../bentobox/challenges/panel/CommonGUI.java | 13 +-- .../challenges/tasks/TryToComplete.java | 65 +++------------ .../bentobox/challenges/utils/Utils.java | 81 +++++++++++++++++++ 3 files changed, 97 insertions(+), 62 deletions(-) create mode 100644 src/main/java/world/bentobox/challenges/utils/Utils.java diff --git a/src/main/java/world/bentobox/challenges/panel/CommonGUI.java b/src/main/java/world/bentobox/challenges/panel/CommonGUI.java index 484640a..e9870b9 100644 --- a/src/main/java/world/bentobox/challenges/panel/CommonGUI.java +++ b/src/main/java/world/bentobox/challenges/panel/CommonGUI.java @@ -1,7 +1,6 @@ package world.bentobox.challenges.panel; -import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.World; import org.bukkit.enchantments.Enchantment; @@ -20,8 +19,8 @@ import world.bentobox.challenges.ChallengesAddon; import world.bentobox.challenges.ChallengesManager; import world.bentobox.challenges.database.object.Challenge; import world.bentobox.challenges.database.object.ChallengeLevel; -import world.bentobox.challenges.utils.GuiUtils; import world.bentobox.challenges.utils.LevelStatus; +import world.bentobox.challenges.utils.Utils; /** @@ -631,8 +630,7 @@ public abstract class CommonGUI { result.add(this.user.getTranslation("challenges.gui.challenge-description.required-items")); - for (ItemStack itemStack : challenge.getRequiredItems()) - { + Utils.groupEqualItems(challenge.getRequiredItems()).forEach(itemStack -> { result.add(this.user.getTranslation("challenges.gui.descriptions.item", "[item]", itemStack.getType().name(), "[count]", Integer.toString(itemStack.getAmount()))); @@ -646,9 +644,12 @@ public abstract class CommonGUI for (Map.Entry entry : itemStack.getEnchantments().entrySet()) { result.add(this.user.getTranslation("challenges.gui.descriptions.item-enchant", - "[enchant]", entry.getKey().getKey().getKey(), "[level]", Integer.toString(entry.getValue()))); + "[enchant]", + entry.getKey().getKey().getKey(), + "[level]", + Integer.toString(entry.getValue()))); } - } + }); } if (challenge.getChallengeType().equals(Challenge.ChallengeType.ISLAND) && diff --git a/src/main/java/world/bentobox/challenges/tasks/TryToComplete.java b/src/main/java/world/bentobox/challenges/tasks/TryToComplete.java index 1bc0e20..f76e513 100644 --- a/src/main/java/world/bentobox/challenges/tasks/TryToComplete.java +++ b/src/main/java/world/bentobox/challenges/tasks/TryToComplete.java @@ -25,6 +25,7 @@ import world.bentobox.challenges.ChallengesManager; import world.bentobox.challenges.database.object.Challenge; import world.bentobox.challenges.database.object.Challenge.ChallengeType; import world.bentobox.challenges.database.object.ChallengeLevel; +import world.bentobox.challenges.utils.Utils; /** @@ -703,48 +704,19 @@ public class TryToComplete private ChallengeResult checkInventory(int maxTimes) { // Run through inventory - List requiredItems = new ArrayList<>(this.challenge.getRequiredItems().size()); + List requiredItems; // Players in creative game mode has got all items. No point to search for them. if (this.user.getPlayer().getGameMode() != GameMode.CREATIVE) { - // Group all equal items in singe stack, as otherwise it will be too complicated to check if all - // items are in players inventory. - for (ItemStack item : this.challenge.getRequiredItems()) - { - boolean isUnique = true; - - int i = 0; - final int requiredSize = requiredItems.size(); - - while (i < requiredSize && isUnique) - { - ItemStack required = requiredItems.get(i); - - // Merge items which meta can be ignored or is similar to item in required list. - if (this.canIgnoreMeta(item.getType()) && item.getType().equals(required.getType()) || - required.isSimilar(item)) - { - required.setAmount(required.getAmount() + item.getAmount()); - isUnique = false; - } - - i++; - } - - if (isUnique) - { - // The same issue as in other places. Clone prevents from changing original item. - requiredItems.add(item.clone()); - } - } + requiredItems = Utils.groupEqualItems(this.challenge.getRequiredItems()); // Check if all required items are in players inventory. for (ItemStack required : requiredItems) { int numInInventory; - if (this.canIgnoreMeta(required.getType())) + if (Utils.canIgnoreMeta(required.getType())) { numInInventory = Arrays.stream(this.user.getInventory().getContents()). @@ -774,6 +746,10 @@ public class TryToComplete maxTimes = Math.min(maxTimes, numInInventory / required.getAmount()); } } + else + { + requiredItems = Collections.emptyList(); + } // Return the result return new ChallengeResult(). @@ -798,7 +774,7 @@ public class TryToComplete List itemsInInventory; - if (this.canIgnoreMeta(required.getType())) + if (Utils.canIgnoreMeta(required.getType())) { // Use collecting method that ignores item meta. itemsInInventory = Arrays.stream(user.getInventory().getContents()). @@ -849,29 +825,6 @@ public class TryToComplete } - /** - * This method returns if meta data of these items can be ignored. It means, that items will be searched - * and merged by they type instead of using ItemStack#isSimilar(ItemStack) method. - * - * This limits custom Challenges a lot. It comes from ASkyBlock times, and that is the reason why it is - * still here. It would be a great Challenge that could be completed by collecting 4 books, that cannot - * be crafted. Unfortunately, this prevents it. - * The same happens with firework rockets, enchanted books and filled maps. - * In future it should be able to specify, which items meta should be ignored when adding item in required - * item list. - * - * @param material Material that need to be checked. - * @return True if material meta can be ignored, otherwise false. - */ - private boolean canIgnoreMeta(Material material) - { - return material.equals(Material.FIREWORK_ROCKET) || - material.equals(Material.ENCHANTED_BOOK) || - material.equals(Material.WRITTEN_BOOK) || - material.equals(Material.FILLED_MAP); - } - - // --------------------------------------------------------------------- // Section: Island Challenge // --------------------------------------------------------------------- diff --git a/src/main/java/world/bentobox/challenges/utils/Utils.java b/src/main/java/world/bentobox/challenges/utils/Utils.java new file mode 100644 index 0000000..8f59a9d --- /dev/null +++ b/src/main/java/world/bentobox/challenges/utils/Utils.java @@ -0,0 +1,81 @@ +package world.bentobox.challenges.utils; + + +import org.bukkit.Material; +import org.bukkit.inventory.ItemStack; +import java.util.ArrayList; +import java.util.List; + + +/** + * Util methods used in different situations. + */ +public class Utils +{ + /** + * This method groups input items in single itemstack with correct amount and returns it. + * Allows to remove duplicate items from list. + * @param requiredItems Input item list + * @return List that contains unique items that cannot be grouped. + */ + public static List groupEqualItems(List requiredItems) + { + List returnItems = new ArrayList<>(requiredItems.size()); + + // Group all equal items in singe stack, as otherwise it will be too complicated to check if all + // items are in players inventory. + for (ItemStack item : requiredItems) + { + boolean isUnique = true; + + int i = 0; + final int requiredSize = returnItems.size(); + + while (i < requiredSize && isUnique) + { + ItemStack required = returnItems.get(i); + + // Merge items which meta can be ignored or is similar to item in required list. + if (Utils.canIgnoreMeta(item.getType()) && item.getType().equals(required.getType()) || + required.isSimilar(item)) + { + required.setAmount(required.getAmount() + item.getAmount()); + isUnique = false; + } + + i++; + } + + if (isUnique) + { + // The same issue as in other places. Clone prevents from changing original item. + returnItems.add(item.clone()); + } + } + + return returnItems; + } + + + /** + * This method returns if meta data of these items can be ignored. It means, that items will be searched + * and merged by they type instead of using ItemStack#isSimilar(ItemStack) method. + * + * This limits custom Challenges a lot. It comes from ASkyBlock times, and that is the reason why it is + * still here. It would be a great Challenge that could be completed by collecting 4 books, that cannot + * be crafted. Unfortunately, this prevents it. + * The same happens with firework rockets, enchanted books and filled maps. + * In future it should be able to specify, which items meta should be ignored when adding item in required + * item list. + * + * @param material Material that need to be checked. + * @return True if material meta can be ignored, otherwise false. + */ + public static boolean canIgnoreMeta(Material material) + { + return material.equals(Material.FIREWORK_ROCKET) || + material.equals(Material.ENCHANTED_BOOK) || + material.equals(Material.WRITTEN_BOOK) || + material.equals(Material.FILLED_MAP); + } +}