Merge branch 'fix/ecoenchant' into feature/datapack

This commit is contained in:
alexcrea 2025-05-03 06:36:36 +02:00
commit c7cccc906f
No known key found for this signature in database
GPG key ID: 027DD67D2D3280C5
5 changed files with 130 additions and 39 deletions

View file

@ -76,7 +76,7 @@ public class CAEnchantmentRegistry {
*/
public boolean register(@NotNull CAEnchantment enchantment) {
if (byKeyMap.containsKey(enchantment.getKey())) {
if (!enchantment.equals(byKeyMap.get(enchantment.getKey()))) {
if (Objects.equals(enchantment, byKeyMap.get(enchantment.getKey()))) {
// We are trying to register the exact same enchantment. so we just skip it.
return false;
}

View file

@ -18,6 +18,7 @@ import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.logging.Level;
/**
@ -163,7 +164,7 @@ public class CABukkitEnchantment extends CAEnchantmentBase {
return false;
}
return this.bukkit.equals(other.getEnchant());
return Objects.equals(this.bukkit, other.getEnchant());
}
}

View file

@ -2,6 +2,7 @@ package io.delilaheve.util
import io.delilaheve.CustomAnvil
import io.delilaheve.util.EnchantmentUtil.enchantmentName
import org.bukkit.NamespacedKey
import xyz.alexcrea.cuanvil.config.ConfigHolder
import xyz.alexcrea.cuanvil.config.WorkPenaltyType
import xyz.alexcrea.cuanvil.config.WorkPenaltyType.WorkPenaltyPart
@ -51,6 +52,8 @@ object ConfigOptions {
const val DISABLE_MERGE_OVER_ROOT = "disable-merge-over"
const val IMMUTABLE_ENCHANTMENT_LIST = "immutable_enchantments"
// Keys for specific enchantment values
private const val KEY_BOOK = "book"
private const val KEY_ITEM = "item"
@ -478,4 +481,17 @@ object ConfigOptions {
.takeIf { it in ENCHANT_LIMIT_RANGE }
}
fun isImmutable(key: NamespacedKey): Boolean {
val immutables = ConfigHolder.DEFAULT_CONFIG.config.getStringList(IMMUTABLE_ENCHANTMENT_LIST)
// We need to ignore case so can't just check "contain"
for (ench in immutables) {
if (ench.equals(key.toString(), ignoreCase = true) ||
ench.equals(key.key, ignoreCase = true)
)
return true
}
return false
}
}

View file

@ -102,6 +102,35 @@ object DependencyManager {
// Then handle plugin reload
ecoEnchantCompatibility?.handleConfigReload()
}
// Return true if should bypass (either by a dependency or error)
// called before immutability test
fun earlyTryEventPreAnvilBypass(event: PrepareAnvilEvent, player: HumanEntity): Boolean {
try {
return earlyUnsafeTryEventPreAnvilBypass(event, player)
} catch (e: Exception) {
CustomAnvil.instance.logger.log(
Level.SEVERE,
"Error while trying to handle custom anvil supported plugin: ",
e
)
// Just in case to avoid illegal items
event.inventory.setItem(ANVIL_OUTPUT_SLOT, null)
// Finally, warn the player, maybe a lot of time but better warn than do nothing
event.view.player.sendMessage(ChatColor.RED.toString() + "Error while handling the anvil.")
return true
}
}
private fun earlyUnsafeTryEventPreAnvilBypass(event: PrepareAnvilEvent, player: HumanEntity): Boolean {
var bypass = false
// Test if the inventory is a gui(version specific)
if (externGuiTester?.testIfGui(event.view) == true) bypass = true
return bypass
}
// Return true if should bypass (either by a dependency or error)
fun tryEventPreAnvilBypass(event: PrepareAnvilEvent, player: HumanEntity): Boolean {
@ -135,10 +164,6 @@ object DependencyManager {
// Test excellent enchantments used prepare anvil
if (!bypass && (excellentEnchantsCompatibility?.testPrepareAnvil(event) == true)) bypass = true
// Test if the inventory is a gui(version specific)
if (!bypass && (externGuiTester?.testIfGui(event.view) == true)) bypass = true
return bypass
}

View file

@ -19,6 +19,8 @@ import org.bukkit.event.Listener
import org.bukkit.event.inventory.PrepareAnvilEvent
import org.bukkit.inventory.AnvilInventory
import org.bukkit.inventory.ItemStack
import org.bukkit.inventory.meta.EnchantmentStorageMeta
import org.bukkit.inventory.meta.ItemMeta
import xyz.alexcrea.cuanvil.dependency.DependencyManager
import xyz.alexcrea.cuanvil.util.*
import xyz.alexcrea.cuanvil.util.UnitRepairUtil.getRepair
@ -45,13 +47,23 @@ class PrepareAnvilListener : Listener {
// Should find player
val player: HumanEntity = InventoryViewUtil.getInstance().getPlayer(event.view)
// Test if the event should bypass custom anvil.
if (DependencyManager.tryEventPreAnvilBypass(event, player)) return
// Test if custom anvil is bypassed before immutability test
if (DependencyManager.earlyTryEventPreAnvilBypass(event, player)) return
val inventory = event.inventory
val first = inventory.getItem(ANVIL_INPUT_LEFT) ?: return
val second = inventory.getItem(ANVIL_INPUT_RIGHT)
if (isImmutable(first) || isImmutable(second)) {
CustomAnvil.verboseLog("Skipping anvil process as one of the two item is immutable")
event.result = null
return
}
// Test if the event should bypass custom anvil.
if (DependencyManager.tryEventPreAnvilBypass(event, player)) return
if (!player.hasPermission(CustomAnvil.affectedByPluginPermission)) return
// Test custom recipe
@ -80,10 +92,38 @@ class PrepareAnvilListener : Listener {
}
private fun isImmutable(item: ItemStack?): Boolean {
if (item == null) return false
val meta = item.itemMeta
return meta != null &&
(hasImmutableEnchants(meta) || hasImmutableStoredEnchants(meta))
}
private fun hasImmutableEnchants(meta: ItemMeta): Boolean {
if (!meta.hasEnchants()) return false
for (enchant in meta.enchants.keys) {
if (ConfigOptions.isImmutable(enchant.key)) return true
}
return false
}
private fun hasImmutableStoredEnchants(meta: ItemMeta): Boolean {
if (meta !is EnchantmentStorageMeta || !meta.hasStoredEnchants()) return false
for (enchant in meta.storedEnchants.keys) {
if (ConfigOptions.isImmutable(enchant.key)) return true
}
return false
}
// return true if a custom recipe exist with these ingredients
private fun testCustomRecipe(event: PrepareAnvilEvent, inventory: AnvilInventory,
private fun testCustomRecipe(
event: PrepareAnvilEvent, inventory: AnvilInventory,
player: HumanEntity,
first: ItemStack, second: ItemStack?): Boolean {
first: ItemStack, second: ItemStack?
): Boolean {
val recipe = CustomRecipeUtil.getCustomRecipe(first, second)
CustomAnvil.verboseLog("custom recipe not null? ${recipe != null}")
if (recipe == null) return false
@ -105,8 +145,10 @@ class PrepareAnvilListener : Listener {
return true
}
private fun doRenaming(event: PrepareAnvilEvent, inventory: AnvilInventory,
player: HumanEntity, first: ItemStack) {
private fun doRenaming(
event: PrepareAnvilEvent, inventory: AnvilInventory,
player: HumanEntity, first: ItemStack
) {
val resultItem = first.clone()
var anvilCost = handleRename(resultItem, inventory, player)
@ -134,10 +176,12 @@ class PrepareAnvilListener : Listener {
if (ConfigOptions.renameColorPossible && inventoryName != null) {
val resultString = StringBuilder(inventoryName)
useColor = AnvilColorUtil.handleColor(resultString, player,
useColor = AnvilColorUtil.handleColor(
resultString, player,
ConfigOptions.permissionNeededForColor,
ConfigOptions.allowColorCode, ConfigOptions.allowHexadecimalColor,
AnvilColorUtil.ColorUseType.RENAME)
AnvilColorUtil.ColorUseType.RENAME
)
if (useColor) {
inventoryName = resultString.toString()
@ -165,9 +209,11 @@ class PrepareAnvilListener : Listener {
return 0
}
private fun doMerge(event: PrepareAnvilEvent, inventory: AnvilInventory,
private fun doMerge(
event: PrepareAnvilEvent, inventory: AnvilInventory,
player: HumanEntity,
first: ItemStack, second: ItemStack) {
first: ItemStack, second: ItemStack
) {
val newEnchants = first.findEnchantments()
.combineWith(second.findEnchantments(), first, player)
val resultItem = first.clone()
@ -201,8 +247,10 @@ class PrepareAnvilListener : Listener {
}
// return true if there is a valid unit repair with these ingredients
private fun testUnitRepair(event: PrepareAnvilEvent, inventory: AnvilInventory, player: HumanEntity,
first: ItemStack, second: ItemStack): Boolean {
private fun testUnitRepair(
event: PrepareAnvilEvent, inventory: AnvilInventory, player: HumanEntity,
first: ItemStack, second: ItemStack
): Boolean {
val unitRepairAmount = first.getRepair(second) ?: return false
val resultItem = first.clone()
@ -228,16 +276,17 @@ class PrepareAnvilListener : Listener {
return true
}
private fun testLoreEdit(event: PrepareAnvilEvent, inventory: AnvilInventory, player: HumanEntity,
first: ItemStack, second: ItemStack): Boolean {
private fun testLoreEdit(
event: PrepareAnvilEvent, inventory: AnvilInventory, player: HumanEntity,
first: ItemStack, second: ItemStack
): Boolean {
val type = second.type
var result: ItemStack? = null
val xpCost = AtomicInteger()
if (Material.WRITABLE_BOOK == type) {
result = AnvilLoreEditUtil.tryLoreEditByBook(player, first, second, xpCost)
}
else if(Material.PAPER == type) {
} else if (Material.PAPER == type) {
result = AnvilLoreEditUtil.tryLoreEditByPaper(player, first, second, xpCost)
}