diff --git a/src/main/java/xyz/alexcrea/cuanvil/enchant/CAEnchantment.java b/src/main/java/xyz/alexcrea/cuanvil/enchant/CAEnchantment.java index f31fae5..d0847a7 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/enchant/CAEnchantment.java +++ b/src/main/java/xyz/alexcrea/cuanvil/enchant/CAEnchantment.java @@ -1,6 +1,7 @@ package xyz.alexcrea.cuanvil.enchant; import io.delilaheve.util.ItemUtil; +import org.bukkit.Material; import org.bukkit.NamespacedKey; import org.bukkit.entity.HumanEntity; import org.bukkit.inventory.ItemStack; @@ -16,7 +17,7 @@ import xyz.alexcrea.cuanvil.group.EnchantConflictGroup; import java.util.Collection; import java.util.HashMap; import java.util.Map; -import java.util.Set; +import java.util.function.Supplier; /** * Represent an enchantment compatible with Custom Anvil. @@ -65,14 +66,40 @@ public interface CAEnchantment { */ boolean isAllowed(@NotNull HumanEntity player); + /** + * Add a conflict to this enchantment conflict list. + * @param conflict The conflict to add. + */ void addConflict(@NotNull EnchantConflictGroup conflict); + + /** + * Remove a conflict from the conflict list of this enchantment. + * @param conflict The conflict to remove from this enchantment. + */ void removeConflict(@NotNull EnchantConflictGroup conflict); + /** + * Clear Custom Anvil conflicts for this enchantment. + */ void clearConflict(); - @NotNull Set getConflicts(); + /** + * Get a collection of Custom Anvil conflict containing this enchantment. + * @return A collection of Custom Anvil conflict containing this enchantment. + */ + @NotNull Collection getConflicts(); - @NotNull ConflictType testConflict(); + /** + * Test if the provided item can be compatible with this + * @param baseEnchantments Validated enchantments for the item. + * @param itemMat Material of the tested item. + * @param itemSupply Provide a new instance of used item stack but with baseEnchantments as enchantments. + * @return Type of conflict this enchantment has with the provided item. + */ + @NotNull + ConflictType testConflict(@NotNull Map baseEnchantments, + @NotNull Material itemMat, + @NotNull Supplier itemSupply); /** * Get current level of the enchantment. diff --git a/src/main/java/xyz/alexcrea/cuanvil/enchant/CAEnchantmentBase.java b/src/main/java/xyz/alexcrea/cuanvil/enchant/CAEnchantmentBase.java index 2ba57d2..5ebcba6 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/enchant/CAEnchantmentBase.java +++ b/src/main/java/xyz/alexcrea/cuanvil/enchant/CAEnchantmentBase.java @@ -1,5 +1,6 @@ package xyz.alexcrea.cuanvil.enchant; +import org.bukkit.Material; import org.bukkit.NamespacedKey; import org.bukkit.entity.HumanEntity; import org.bukkit.inventory.ItemStack; @@ -9,8 +10,11 @@ import org.jetbrains.annotations.Nullable; import xyz.alexcrea.cuanvil.group.ConflictType; import xyz.alexcrea.cuanvil.group.EnchantConflictGroup; -import java.util.HashSet; -import java.util.Set; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.function.Supplier; public abstract class CAEnchantmentBase implements CAEnchantment { @@ -22,7 +26,7 @@ public abstract class CAEnchantmentBase implements CAEnchantment { private final EnchantmentRarity defaultRarity; private final int defaultMaxLevel; - private final Set conflicts; + private final List conflicts; /** * Constructor of Wrapped Enchantment. @@ -38,10 +42,9 @@ public abstract class CAEnchantmentBase implements CAEnchantment { this.name = key.getKey(); this.defaultMaxLevel = defaultMaxLevel; - if(defaultRarity == null) this.defaultRarity = EnchantmentRarity.COMMON; - else this.defaultRarity = defaultRarity; + this.defaultRarity = Objects.requireNonNullElse(defaultRarity, EnchantmentRarity.COMMON); - this.conflicts = new HashSet<>(); + this.conflicts = new ArrayList<>(); } @NotNull @@ -105,12 +108,14 @@ public abstract class CAEnchantmentBase implements CAEnchantment { } @Override - public @NotNull Set getConflicts() { + public @NotNull List getConflicts() { return conflicts; } @Override - public @NotNull ConflictType testConflict() { + public @NotNull ConflictType testConflict(@NotNull Map baseEnchantments, + @NotNull Material itemMat, + @NotNull Supplier itemSupply) { return ConflictType.NO_CONFLICT; } diff --git a/src/main/kotlin/io/delilaheve/AnvilEventListener.kt b/src/main/kotlin/io/delilaheve/AnvilEventListener.kt index a44a7c4..45ea943 100644 --- a/src/main/kotlin/io/delilaheve/AnvilEventListener.kt +++ b/src/main/kotlin/io/delilaheve/AnvilEventListener.kt @@ -99,7 +99,7 @@ class AnvilEventListener(private val packetManager: PacketManager) : Listener { // Test for merge if (first.canMergeWith(second)) { val newEnchants = first.findEnchantments() - .combineWith(second.findEnchantments(), first.type, player) + .combineWith(second.findEnchantments(), first, player) val resultItem = first.clone() resultItem.setEnchantmentsUnsafe(newEnchants) @@ -436,15 +436,15 @@ class AnvilEventListener(private val packetManager: PacketManager) : Listener { val rightIsFormBook = right.isEnchantedBook() val resultEnchs = result.findEnchantments() - val resultEnchsKeys = HashSet(resultEnchs.keys) + val resultEnchsKeys = HashMap(resultEnchs) for (enchantment in right.findEnchantments()) { // count enchant as illegal enchant if it conflicts with another enchant or not in result if ((enchantment.key !in resultEnchsKeys)) { - resultEnchsKeys.add(enchantment.key) + resultEnchsKeys[enchantment.key] = enchantment.value val conflictType = ConfigHolder.CONFLICT_HOLDER.conflictManager.isConflicting( resultEnchsKeys, - result.type, + result, enchantment.key ) resultEnchsKeys.remove(enchantment.key) diff --git a/src/main/kotlin/io/delilaheve/util/EnchantmentUtil.kt b/src/main/kotlin/io/delilaheve/util/EnchantmentUtil.kt index 368c8d9..95bdd36 100644 --- a/src/main/kotlin/io/delilaheve/util/EnchantmentUtil.kt +++ b/src/main/kotlin/io/delilaheve/util/EnchantmentUtil.kt @@ -1,8 +1,8 @@ package io.delilaheve.util import io.delilaheve.CustomAnvil -import org.bukkit.Material import org.bukkit.entity.HumanEntity +import org.bukkit.inventory.ItemStack import xyz.alexcrea.cuanvil.config.ConfigHolder import xyz.alexcrea.cuanvil.enchant.CAEnchantment import xyz.alexcrea.cuanvil.group.ConflictType @@ -25,10 +25,11 @@ object EnchantmentUtil { */ fun Map.combineWith( other: Map, - mat: Material, + item: ItemStack, player: HumanEntity ) = mutableMapOf().apply { putAll(this@combineWith) + other.forEach { (enchantment, level) -> if(!enchantment.isAllowed(player)) return@forEach @@ -44,7 +45,7 @@ object EnchantmentUtil { // Add the enchantment if it doesn't have conflicts, or if player is allowed to bypass enchantment restrictions this[enchantment] = cappedLevel val conflictType = - ConfigHolder.CONFLICT_HOLDER.conflictManager.isConflicting(this.keys, mat, enchantment) + ConfigHolder.CONFLICT_HOLDER.conflictManager.isConflicting(this, item, enchantment) if (!player.hasPermission(CustomAnvil.bypassFusePermission) && (conflictType != ConflictType.NO_CONFLICT) ) { @@ -59,7 +60,7 @@ object EnchantmentUtil { // ... and they are conflicting val conflictType = - ConfigHolder.CONFLICT_HOLDER.conflictManager.isConflicting(this.keys, mat, enchantment) + ConfigHolder.CONFLICT_HOLDER.conflictManager.isConflicting(this, item, enchantment) if ((conflictType != ConflictType.NO_CONFLICT) && !player.hasPermission(CustomAnvil.bypassFusePermission) ) { diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictManager.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictManager.kt index f79e252..4cab56a 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictManager.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/group/EnchantConflictManager.kt @@ -1,12 +1,13 @@ package xyz.alexcrea.cuanvil.group import io.delilaheve.CustomAnvil -import org.bukkit.Material import org.bukkit.NamespacedKey import org.bukkit.configuration.ConfigurationSection import org.bukkit.enchantments.Enchantment +import org.bukkit.inventory.ItemStack import xyz.alexcrea.cuanvil.enchant.CAEnchantment import xyz.alexcrea.cuanvil.enchant.CAEnchantmentRegistry +import java.util.function.Supplier class EnchantConflictManager { @@ -144,14 +145,15 @@ class EnchantConflictManager { return group } - fun isConflicting(base: Set, mat: Material, newEnchant: CAEnchantment): ConflictType { + fun isConflicting(appliedEnchants: Map, item: ItemStack, newEnchant: CAEnchantment): ConflictType { + val mat = item.type CustomAnvil.verboseLog("Testing conflict for ${newEnchant.key} on ${mat.key}") val conflictList = newEnchant.conflicts; var result = ConflictType.NO_CONFLICT for (conflict in conflictList) { CustomAnvil.verboseLog("Is against $conflict") - val allowed = conflict.allowed(base, mat) + val allowed = conflict.allowed(appliedEnchants.keys, mat) CustomAnvil.verboseLog("Was against $conflict and conflicting: ${!allowed} ") if (!allowed) { if (conflict.getEnchants().size <= 1) { @@ -165,11 +167,24 @@ class EnchantConflictManager { } // Test conflict with other conflict system. - val otherConflict = newEnchant.testConflict() + val otherConflict = newEnchant.testConflict(appliedEnchants, mat, reEnchantSupplier(item, appliedEnchants)) return result.getWorstConflict(otherConflict) } + private fun reEnchantSupplier(item: ItemStack, enchantments: Map): Supplier { + return Supplier { + val newItem = item.clone() + + CAEnchantment.clearEnchants(newItem) + enchantments.forEach{//TODO maybe bulk add if possible + enchantment -> enchantment.key.addEnchantmentUnsafe(item, enchantment.value) + } + + return@Supplier newItem; + } + } + } /**