From 1e2acb6f480d7d6507ae13ab19c535355ab5bde0 Mon Sep 17 00:00:00 2001 From: alexcrea Date: Tue, 30 Jun 2026 07:47:41 +0200 Subject: [PATCH] expose more enchantment function to API & use them --- .../alexcrea/cuanvil/api/EnchantmentApi.java | 108 +++++++++++++----- .../kotlin/io/delilaheve/util/ItemUtil.kt | 17 --- .../alexcrea/cuanvil/anvil/AnvilMergeLogic.kt | 16 ++- .../cuanvil/group/EnchantConflictManager.kt | 27 ++--- .../cuanvil/util/anvil/AnvilXpUtil.kt | 8 +- .../cuanvil/util/AnvilFuseTestUtil.java | 3 +- 6 files changed, 107 insertions(+), 72 deletions(-) diff --git a/src/main/java/xyz/alexcrea/cuanvil/api/EnchantmentApi.java b/src/main/java/xyz/alexcrea/cuanvil/api/EnchantmentApi.java index 53c0b324..965d7495 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/api/EnchantmentApi.java +++ b/src/main/java/xyz/alexcrea/cuanvil/api/EnchantmentApi.java @@ -5,6 +5,7 @@ import io.delilaheve.util.ConfigOptions; import org.bukkit.NamespacedKey; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.enchantments.Enchantment; +import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import xyz.alexcrea.cuanvil.config.ConfigHolder; @@ -38,14 +39,14 @@ public class EnchantmentApi { * @param enchantment The enchantment to register * @return True if successful. */ - public static boolean registerEnchantment(@NotNull CAEnchantment enchantment){ - if(!CAEnchantmentRegistry.getInstance().register(enchantment)) return false; + public static boolean registerEnchantment(@NotNull CAEnchantment enchantment) { + if (!CAEnchantmentRegistry.getInstance().register(enchantment)) return false; // Add enchantment to gui. - if(EnchantCostConfigGui.getInstance() != null){ + if (EnchantCostConfigGui.getInstance() != null) { EnchantCostConfigGui.getInstance().updateValueForGeneric(enchantment, true); } - if(EnchantLimitConfigGui.getInstance() != null){ + if (EnchantLimitConfigGui.getInstance() != null) { EnchantLimitConfigGui.getInstance().updateValueForGeneric(enchantment, true); } @@ -62,8 +63,8 @@ public class EnchantmentApi { * @param defaultRarity The default rarity of the provided enchantment * @return True if successful. */ - public static boolean registerEnchantment(@NotNull Enchantment enchantment, @Nullable EnchantmentRarity defaultRarity){ - if(defaultRarity == null) + public static boolean registerEnchantment(@NotNull Enchantment enchantment, @Nullable EnchantmentRarity defaultRarity) { + if (defaultRarity == null) return registerEnchantment(new CABukkitEnchantment(enchantment)); return registerEnchantment(new CABukkitEnchantment(enchantment, defaultRarity)); @@ -77,7 +78,7 @@ public class EnchantmentApi { * @param enchantment The enchantment to register * @return True if successful. */ - public static boolean registerEnchantment(@NotNull Enchantment enchantment){ + public static boolean registerEnchantment(@NotNull Enchantment enchantment) { return registerEnchantment(new CABukkitEnchantment(enchantment)); } @@ -87,12 +88,12 @@ public class EnchantmentApi { * @param enchantment The enchantment to unregister * @return True if successful. */ - public static boolean unregisterEnchantment(@Nullable CAEnchantment enchantment){ + public static boolean unregisterEnchantment(@Nullable CAEnchantment enchantment) { // Remove from gui - if(EnchantCostConfigGui.getInstance() != null){ + if (EnchantCostConfigGui.getInstance() != null) { EnchantCostConfigGui.getInstance().removeGeneric(enchantment); } - if(EnchantLimitConfigGui.getInstance() != null){ + if (EnchantLimitConfigGui.getInstance() != null) { EnchantLimitConfigGui.getInstance().removeGeneric(enchantment); } @@ -105,7 +106,7 @@ public class EnchantmentApi { * @param key The enchantment key to unregister * @return True if successful. */ - public static boolean unregisterEnchantment(@NotNull NamespacedKey key){ + public static boolean unregisterEnchantment(@NotNull NamespacedKey key) { CAEnchantment enchantment = CAEnchantment.getByKey(key); return unregisterEnchantment(enchantment); } @@ -116,7 +117,7 @@ public class EnchantmentApi { * @param enchantment The enchantment to unregister * @return True if successful. */ - public static boolean unregisterEnchantment(@NotNull Enchantment enchantment){ + public static boolean unregisterEnchantment(@NotNull Enchantment enchantment) { return unregisterEnchantment(enchantment.getKey()); } @@ -127,7 +128,7 @@ public class EnchantmentApi { * @return The custom anvil enchantment of this key. null if not found. */ @Nullable - public static CAEnchantment getByKey(@NotNull NamespacedKey key){ + public static CAEnchantment getByKey(@NotNull NamespacedKey key) { return CAEnchantment.getByKey(key); } @@ -140,7 +141,7 @@ public class EnchantmentApi { */ @Deprecated(since = "1.6.3") @Nullable - public static CAEnchantment getByName(@NotNull String name){ + public static CAEnchantment getByName(@NotNull String name) { return CAEnchantment.getByName(name); } @@ -150,29 +151,31 @@ public class EnchantmentApi { * @param name The name used to fetch * @return List of custom anvil enchantments of this name. May be empty if not found. */ - public static List getListByName(@NotNull String name){ + public static List getListByName(@NotNull String name) { return CAEnchantment.getListByName(name); } /** * Get every registered custom anvil enchantments. + * * @return An immutable map of enchantment key as map key and custom anvil enchantment as value. */ @NotNull - public static Map getRegisteredEnchantments(){ + public static Map getRegisteredEnchantments() { return Collections.unmodifiableMap(CAEnchantmentRegistry.getInstance().registeredEnchantments()); } /** * Write the default level and rarity configuration of the enchantment. + * * @param enchantment The enchantment to write default configuration - * @param override If it should override old configuration + * @param override If it should override old configuration * @return Return false if override is false and a configuration exist. true otherwise. */ - public static boolean writeDefaultConfig(CAEnchantment enchantment, boolean override){ + public static boolean writeDefaultConfig(CAEnchantment enchantment, boolean override) { FileConfiguration config = ConfigHolder.DEFAULT_CONFIG.getConfig(); - if(tryWriteDefaultConfig(config, enchantment, override)){ + if (tryWriteDefaultConfig(config, enchantment, override)) { prepareSaveTask(); } return true; @@ -182,7 +185,7 @@ public class EnchantmentApi { boolean hasChange = false; String levelPath = ConfigOptions.ENCHANT_LIMIT_ROOT + "." + enchantment.getKey(); - if(override || !defaultConfig.isSet(levelPath)){ + if (override || !defaultConfig.isSet(levelPath)) { defaultConfig.set(levelPath, enchantment.defaultMaxLevel()); hasChange = true; } @@ -192,11 +195,11 @@ public class EnchantmentApi { String itemPath = basePath + ".item"; String bookPath = basePath + ".book"; - if(override || !defaultConfig.isSet(itemPath)){ + if (override || !defaultConfig.isSet(itemPath)) { defaultConfig.set(itemPath, rarity.getItemValue()); hasChange = true; } - if(override || !defaultConfig.isSet(bookPath)){ + if (override || !defaultConfig.isSet(bookPath)) { defaultConfig.set(bookPath, rarity.getBookValue()); hasChange = true; } @@ -208,9 +211,9 @@ public class EnchantmentApi { * Prepare a task to save custom recipe configuration. */ private static void prepareSaveTask() { - if(saveChangeTask != null) return; + if (saveChangeTask != null) return; - saveChangeTask = DependencyManager.scheduler.scheduleGlobally(CustomAnvil.instance, ()->{ + saveChangeTask = DependencyManager.scheduler.scheduleGlobally(CustomAnvil.instance, () -> { ConfigHolder.DEFAULT_CONFIG.saveToDisk(true); saveChangeTask = null; }); @@ -220,20 +223,69 @@ public class EnchantmentApi { * Add a bulk get operator. (not needed for proper "bukkit" enchantments) *

* Do not forget to mark your enchantments as {@link CAEnchantment#isGetOptimised() Get Optimized} + * * @param operation An optimised get enchantments operation */ - public static void addBulkGet(@NotNull BulkGetEnchantOperation operation){ + public static void addBulkGet(@NotNull BulkGetEnchantOperation operation) { CAEnchantmentRegistry.getInstance().getOptimisedGetOperators().add(operation); } /** * Add a bulk clean operator. + * * @param operation An optimised clean enchantments operation (not needed for proper "bukkit" enchantments) - *

- * Do not forget to mark your enchantments as {@link CAEnchantment#isCleanOptimised() Clean Optimized} + *

+ * Do not forget to mark your enchantments as {@link CAEnchantment#isCleanOptimised() Clean Optimized} */ - public static void addBulkClean(@NotNull BulkCleanEnchantOperation operation){ + public static void addBulkClean(@NotNull BulkCleanEnchantOperation operation) { CAEnchantmentRegistry.getInstance().getOptimisedCleanOperators().add(operation); } + /** + * Get all the enchantments of an item + * + * @param item The item to get the enchantment from + * @return A map of key of enchantment, value the level of all the enchantments of the item + * @since 1.17.6 + */ + public static Map getEnchantments(@NotNull ItemStack item) { + return CAEnchantment.getEnchants(item); + } + + /** + * Set all the enchantments to an item. Clearing previous enchantments + * + * @param item The item to get the enchantment from + * @param enchants A map of key of enchantment, value the level of all the enchantments + * @since 1.17.6 + */ + public static void setEnchantments(@NotNull ItemStack item, @NotNull Map enchants) { + clearEnchantments(item); + addEnchantments(item, enchants); + } + + /** + * Add enchantment with there respective level. + * If the enchantment is already present it will be overridden to the new level + * + * @param item The item to get the enchantment from + * @param enchants A map of key of enchantment, value the level of the new enchantments + * @since 1.17.6 + */ + public static void addEnchantments(@NotNull ItemStack item, @NotNull Map enchants) { + enchants.forEach((enchantment, level) -> + enchantment.addEnchantmentUnsafe(item, level) + ); + } + + /** + * Clear all the enchantments + * + * @param item The item to clear the enchantments from + * @since 1.17.6 + */ + public static void clearEnchantments(@NotNull ItemStack item) { + CAEnchantment.clearEnchants(item); + } + } diff --git a/src/main/kotlin/io/delilaheve/util/ItemUtil.kt b/src/main/kotlin/io/delilaheve/util/ItemUtil.kt index 25698ad1..bf075231 100644 --- a/src/main/kotlin/io/delilaheve/util/ItemUtil.kt +++ b/src/main/kotlin/io/delilaheve/util/ItemUtil.kt @@ -21,23 +21,6 @@ object ItemUtil { */ fun ItemStack.isEnchantedBook() = type == ENCHANTED_BOOK - /** - * Find the enchantment map for this [ItemStack] and return it as a [MutableMap] - */ - fun ItemStack.findEnchantments(): MutableMap = CAEnchantment.getEnchants(this) - - /** - * Apply an [enchantments] map to this [ItemStack] - */ - fun ItemStack.setEnchantmentsUnsafe(enchantments: Map) { - CAEnchantment.clearEnchants(this) - - enchantments.forEach { (enchantment, level) -> - enchantment.addEnchantmentUnsafe(this, level) - } - - } - private fun maxDamage(damageable: Damageable): Int { val ver = UpdateUtils.currentMinecraftVersion() if(ver.major <= 1 && ver.minor <= 20 && ver.patch < 5) return Integer.MAX_VALUE diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/anvil/AnvilMergeLogic.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/anvil/AnvilMergeLogic.kt index 915a3903..6da9f5d9 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/anvil/AnvilMergeLogic.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/anvil/AnvilMergeLogic.kt @@ -3,10 +3,8 @@ package xyz.alexcrea.cuanvil.anvil import io.delilaheve.CustomAnvil import io.delilaheve.util.ConfigOptions import io.delilaheve.util.EnchantmentUtil.combineWith -import io.delilaheve.util.ItemUtil.findEnchantments import io.delilaheve.util.ItemUtil.isEnchantedBook import io.delilaheve.util.ItemUtil.repairFrom -import io.delilaheve.util.ItemUtil.setEnchantmentsUnsafe import io.delilaheve.util.ItemUtil.unitRepair import org.bukkit.ChatColor import org.bukkit.Material @@ -17,6 +15,7 @@ import org.bukkit.inventory.InventoryView import org.bukkit.inventory.ItemStack import org.bukkit.inventory.meta.ItemMeta import org.bukkit.persistence.PersistentDataType +import xyz.alexcrea.cuanvil.api.EnchantmentApi import xyz.alexcrea.cuanvil.dependency.DependencyManager import xyz.alexcrea.cuanvil.dialog.AnvilRenameDialog import xyz.alexcrea.cuanvil.enchant.CAEnchantment @@ -189,14 +188,19 @@ object AnvilMergeLogic { player: Player, first: ItemStack, second: ItemStack ): AnvilResult { - val newEnchants = first.findEnchantments() - .combineWith(second.findEnchantments(), first, player) - var hasChanged = !isIdentical(first.findEnchantments(), newEnchants) + val firstEnchants = EnchantmentApi.getEnchantments(first) + val secondEnchants = EnchantmentApi.getEnchantments(second) + + // newEnchants will be mutated by combineWith + val newEnchants = HashMap(firstEnchants) + newEnchants.combineWith(secondEnchants, first, player) + + var hasChanged = !isIdentical(firstEnchants, newEnchants) val resultItem = DependencyManager.cloneItem(player, first) val cost = AnvilCost() if (hasChanged) { - resultItem.setEnchantmentsUnsafe(newEnchants) + EnchantmentApi.setEnchantments(resultItem, newEnchants) // Calculate enchantment cost AnvilXpUtil.getRightValues(first, second, resultItem, cost) } diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictManager.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictManager.kt index 38d54764..5b256dd8 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictManager.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictManager.kt @@ -5,6 +5,7 @@ import org.bukkit.NamespacedKey import org.bukkit.configuration.ConfigurationSection import org.bukkit.enchantments.Enchantment import org.bukkit.inventory.ItemStack +import xyz.alexcrea.cuanvil.api.EnchantmentApi import xyz.alexcrea.cuanvil.enchant.AdditionalTestEnchantment import xyz.alexcrea.cuanvil.enchant.CAEnchantment import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry @@ -66,7 +67,7 @@ class EnchantConflictManager { val keys = config.getKeys(false) for (key in keys) { val section = config.getConfigurationSection(key) - if(section == null) { + if (section == null) { warnBadKey(key) continue } @@ -140,8 +141,12 @@ class EnchantConflictManager { return conflict } - private fun fetchConditionalRestriction(restrictions: MutableMap, section: ConfigurationSection?, conflictName: String) { - if(section == null) return + private fun fetchConditionalRestriction( + restrictions: MutableMap, + section: ConfigurationSection?, + conflictName: String + ) { + if (section == null) return for (enchantName in section.getKeys(false)) { val enchants = getEnchantByIdentifier(enchantName) if (enchants.isEmpty()) { @@ -150,7 +155,7 @@ class EnchantConflictManager { } val value = section.getInt(enchantName, -1) - if(value < 0) continue + if (value < 0) continue for (enchant in enchants) { val previous = restrictions.getOrDefault(enchant, value) @@ -259,7 +264,8 @@ class EnchantConflictManager { } if ((result != ConflictType.ITEM_CONFLICT) && (newEnchant is AdditionalTestEnchantment)) { - val partialItem = createPartialResult(item, immutableEnchants) + val partialItem = item.clone() + EnchantmentApi.setEnchantments(partialItem, immutableEnchants) if (newEnchant.isItemConflict(immutableEnchants, type, partialItem)) { return ConflictType.ITEM_CONFLICT @@ -270,17 +276,6 @@ class EnchantConflictManager { return result } - private fun createPartialResult(item: ItemStack, enchantments: Map): ItemStack { - val newItem = item.clone() - - CAEnchantment.clearEnchants(newItem) - enchantments.forEach { enchantment -> - enchantment.key.addEnchantmentUnsafe(newItem, enchantment.value) - } - - return newItem - } - } /** diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/anvil/AnvilXpUtil.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/anvil/AnvilXpUtil.kt index 63dc9d03..9d2f5420 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/anvil/AnvilXpUtil.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/util/anvil/AnvilXpUtil.kt @@ -3,7 +3,6 @@ package xyz.alexcrea.cuanvil.util.anvil import io.delilaheve.CustomAnvil import io.delilaheve.util.ConfigOptions import io.delilaheve.util.EnchantmentUtil.enchantmentName -import io.delilaheve.util.ItemUtil.findEnchantments import io.delilaheve.util.ItemUtil.isEnchantedBook import org.bukkit.GameMode import org.bukkit.NamespacedKey @@ -17,6 +16,7 @@ import org.bukkit.persistence.PersistentDataType import xyz.alexcrea.cuanvil.anvil.AnvilCost import xyz.alexcrea.cuanvil.anvil.AnvilMergeLogic.AnvilResult import xyz.alexcrea.cuanvil.anvil.AnvilUseType +import xyz.alexcrea.cuanvil.api.EnchantmentApi import xyz.alexcrea.cuanvil.config.ConfigHolder import xyz.alexcrea.cuanvil.dependency.DependencyManager import xyz.alexcrea.cuanvil.dependency.economy.EconomyManager @@ -247,8 +247,8 @@ object AnvilXpUtil { // Calculate right value and illegal enchant penalty val rightIsFormBook = right.isEnchantedBook() - val rightEnchs = right.findEnchantments() - val resultEnchs = result.findEnchantments() + val rightEnchs = EnchantmentApi.getEnchantments(right) + val resultEnchs = EnchantmentApi.getEnchantments(result) val resultEnchsKeys = HashMap(resultEnchs) var rightValue = 0 @@ -282,7 +282,7 @@ object AnvilXpUtil { } if(ConfigOptions.includeLeftEnchantmentForCost) { val leftIsFormBook = left.isEnchantedBook() - val leftEnchs = left.findEnchantments() + val leftEnchs = EnchantmentApi.getEnchantments(left) for (enchantment in leftEnchs) { // Do not process enchantment that are present on the sacrifice if(rightEnchs.contains(enchantment.key)) continue diff --git a/src/test/java/xyz/alexcrea/cuanvil/util/AnvilFuseTestUtil.java b/src/test/java/xyz/alexcrea/cuanvil/util/AnvilFuseTestUtil.java index 6f5c7bb8..fefec130 100644 --- a/src/test/java/xyz/alexcrea/cuanvil/util/AnvilFuseTestUtil.java +++ b/src/test/java/xyz/alexcrea/cuanvil/util/AnvilFuseTestUtil.java @@ -13,6 +13,7 @@ import org.bukkit.inventory.meta.Repairable; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.junit.jupiter.api.Assertions; +import xyz.alexcrea.cuanvil.api.EnchantmentApi; import xyz.alexcrea.cuanvil.data.AnvilClickTestData; import xyz.alexcrea.cuanvil.data.AnvilFuseTestData; import xyz.alexcrea.cuanvil.enchant.CAEnchantment; @@ -47,7 +48,7 @@ public class AnvilFuseTestUtil { } ItemStack item = new ItemStack(material); - ItemUtil.INSTANCE.setEnchantmentsUnsafe(item, enchantmentMap); + EnchantmentApi.setEnchantments(item, enchantmentMap); ItemMeta meta = item.getItemMeta(); ((Repairable) meta).setRepairCost(repairCost);