From 625b981b81bf9589b64e92ddc8e8fedaa340a2a6 Mon Sep 17 00:00:00 2001 From: Auxilor Date: Mon, 26 Jul 2021 18:38:12 +0100 Subject: [PATCH] Added support for enchantments in recipes --- .../java/com/willfp/eco/core/items/Items.java | 69 +++++++++++++++++-- .../recipe/parts/ModifiedTestableItem.java | 58 ++++++++++++++++ 2 files changed, 121 insertions(+), 6 deletions(-) create mode 100644 eco-api/src/main/java/com/willfp/eco/core/recipe/parts/ModifiedTestableItem.java diff --git a/eco-api/src/main/java/com/willfp/eco/core/items/Items.java b/eco-api/src/main/java/com/willfp/eco/core/items/Items.java index 130098ae7..6bc6b0c24 100644 --- a/eco-api/src/main/java/com/willfp/eco/core/items/Items.java +++ b/eco-api/src/main/java/com/willfp/eco/core/items/Items.java @@ -1,15 +1,21 @@ package com.willfp.eco.core.items; +import com.willfp.eco.core.items.builder.ItemBuilder; +import com.willfp.eco.core.items.builder.ItemStackBuilder; import com.willfp.eco.core.recipe.parts.EmptyTestableItem; import com.willfp.eco.core.recipe.parts.MaterialTestableItem; +import com.willfp.eco.core.recipe.parts.ModifiedTestableItem; import com.willfp.eco.core.recipe.parts.TestableStack; import com.willfp.eco.util.NamespacedKeyUtils; import lombok.experimental.UtilityClass; import org.bukkit.Material; import org.bukkit.NamespacedKey; +import org.bukkit.enchantments.Enchantment; import org.bukkit.inventory.ItemStack; +import org.bukkit.inventory.meta.ItemMeta; import org.jetbrains.annotations.NotNull; +import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -54,14 +60,21 @@ public void removeCustomItem(@NotNull final NamespacedKey key) { * @return The found testable item, or an empty item if not found. */ public TestableItem lookup(@NotNull final String key) { - String[] split = key.toLowerCase().split(":"); + String[] args = key.split(" "); + if (args.length == 0) { + return new EmptyTestableItem(); + } + + TestableItem item = null; + + String[] split = args[0].toLowerCase().split(":"); if (split.length == 1) { Material material = Material.getMaterial(key.toUpperCase()); if (material == null || material == Material.AIR) { return new EmptyTestableItem(); } - return new MaterialTestableItem(material); + item = new MaterialTestableItem(material); } if (split.length == 2) { @@ -72,18 +85,62 @@ public TestableItem lookup(@NotNull final String key) { if (material == null || material == Material.AIR) { return new EmptyTestableItem(); } - return new TestableStack(new MaterialTestableItem(material), Integer.parseInt(split[1])); + item = new TestableStack(new MaterialTestableItem(material), Integer.parseInt(split[1])); } else { - return part; + item = part; } } if (split.length == 3) { CustomItem part = REGISTRY.get(NamespacedKeyUtils.create(split[0], split[1])); - return part == null ? new EmptyTestableItem() : new TestableStack(part, Integer.parseInt(split[2])); + item = part == null ? new EmptyTestableItem() : new TestableStack(part, Integer.parseInt(split[2])); + } + + if (item == null || item instanceof EmptyTestableItem) { + return new EmptyTestableItem(); + } + + String[] enchantArgs = Arrays.copyOfRange(args, 1, args.length); + + Map requiredEnchantments = new HashMap<>(); + + for (String enchantArg : enchantArgs) { + String[] enchantArgSplit = enchantArg.split(":"); + + Enchantment enchantment = Enchantment.getByKey(NamespacedKey.minecraft(enchantArgSplit[0].toLowerCase())); + int level = Integer.parseInt(enchantArgSplit[1]); + + requiredEnchantments.put(enchantment, level); } - return new EmptyTestableItem(); + ItemBuilder builder = new ItemStackBuilder(item.getItem()); + requiredEnchantments.forEach(builder::addEnchantment); + ItemStack example = builder.build(); + + return new ModifiedTestableItem( + item, + itemStack -> { + if (!itemStack.hasItemMeta()) { + return false; + } + + ItemMeta meta = itemStack.getItemMeta(); + + assert meta != null; + + for (Map.Entry entry : requiredEnchantments.entrySet()) { + if (!meta.hasEnchant(entry.getKey())) { + return false; + } + if (meta.getEnchantLevel(entry.getKey()) < entry.getValue()) { + return false; + } + } + + return true; + }, + example + ); } /** diff --git a/eco-api/src/main/java/com/willfp/eco/core/recipe/parts/ModifiedTestableItem.java b/eco-api/src/main/java/com/willfp/eco/core/recipe/parts/ModifiedTestableItem.java new file mode 100644 index 000000000..6ee6941a1 --- /dev/null +++ b/eco-api/src/main/java/com/willfp/eco/core/recipe/parts/ModifiedTestableItem.java @@ -0,0 +1,58 @@ +package com.willfp.eco.core.recipe.parts; + +import com.willfp.eco.core.items.TestableItem; +import lombok.Getter; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.function.Predicate; + +public class ModifiedTestableItem implements TestableItem { + /** + * The item. + */ + private final TestableItem handle; + + /** + * The amount. + */ + @Getter + private final Predicate test; + + /** + * The item for the modified test. + */ + private final ItemStack example; + + /** + * Create a new modified testable item. + * + * @param item The item. + * @param test The test. + * @param example The example. + */ + public ModifiedTestableItem(@NotNull final TestableItem item, + @NotNull final Predicate test, + @NotNull final ItemStack example) { + this.handle = item; + this.test = test; + this.example = example; + } + + /** + * If the item matches the material. + * + * @param itemStack The item to test. + * @return If the item is of the specified material. + */ + @Override + public boolean matches(@Nullable final ItemStack itemStack) { + return itemStack != null && handle.matches(itemStack) && test.test(itemStack); + } + + @Override + public ItemStack getItem() { + return example; + } +}