mirror of
https://github.com/alexcrea/CustomAnvil.git
synced 2026-06-23 16:16:17 +02:00
Merge branch 'fix/ecoenchant' into feature/datapack
This commit is contained in:
commit
c7cccc906f
5 changed files with 130 additions and 39 deletions
|
|
@ -76,12 +76,12 @@ public class CAEnchantmentRegistry {
|
||||||
*/
|
*/
|
||||||
public boolean register(@NotNull CAEnchantment enchantment) {
|
public boolean register(@NotNull CAEnchantment enchantment) {
|
||||||
if (byKeyMap.containsKey(enchantment.getKey())) {
|
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.
|
// We are trying to register the exact same enchantment. so we just skip it.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(ConfigHolder.DEFAULT_CONFIG.getConfig().getBoolean("caution_secret_do_not_log_duplicated_registered_key", false)){
|
if (ConfigHolder.DEFAULT_CONFIG.getConfig().getBoolean("caution_secret_do_not_log_duplicated_registered_key", false)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ import java.lang.reflect.Method;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -163,7 +164,7 @@ public class CABukkitEnchantment extends CAEnchantmentBase {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.bukkit.equals(other.getEnchant());
|
return Objects.equals(this.bukkit, other.getEnchant());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package io.delilaheve.util
|
||||||
|
|
||||||
import io.delilaheve.CustomAnvil
|
import io.delilaheve.CustomAnvil
|
||||||
import io.delilaheve.util.EnchantmentUtil.enchantmentName
|
import io.delilaheve.util.EnchantmentUtil.enchantmentName
|
||||||
|
import org.bukkit.NamespacedKey
|
||||||
import xyz.alexcrea.cuanvil.config.ConfigHolder
|
import xyz.alexcrea.cuanvil.config.ConfigHolder
|
||||||
import xyz.alexcrea.cuanvil.config.WorkPenaltyType
|
import xyz.alexcrea.cuanvil.config.WorkPenaltyType
|
||||||
import xyz.alexcrea.cuanvil.config.WorkPenaltyType.WorkPenaltyPart
|
import xyz.alexcrea.cuanvil.config.WorkPenaltyType.WorkPenaltyPart
|
||||||
|
|
@ -51,6 +52,8 @@ object ConfigOptions {
|
||||||
|
|
||||||
const val DISABLE_MERGE_OVER_ROOT = "disable-merge-over"
|
const val DISABLE_MERGE_OVER_ROOT = "disable-merge-over"
|
||||||
|
|
||||||
|
const val IMMUTABLE_ENCHANTMENT_LIST = "immutable_enchantments"
|
||||||
|
|
||||||
// Keys for specific enchantment values
|
// Keys for specific enchantment values
|
||||||
private const val KEY_BOOK = "book"
|
private const val KEY_BOOK = "book"
|
||||||
private const val KEY_ITEM = "item"
|
private const val KEY_ITEM = "item"
|
||||||
|
|
@ -478,4 +481,17 @@ object ConfigOptions {
|
||||||
.takeIf { it in ENCHANT_LIMIT_RANGE }
|
.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
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,35 @@ object DependencyManager {
|
||||||
// Then handle plugin reload
|
// Then handle plugin reload
|
||||||
ecoEnchantCompatibility?.handleConfigReload()
|
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)
|
// Return true if should bypass (either by a dependency or error)
|
||||||
fun tryEventPreAnvilBypass(event: PrepareAnvilEvent, player: HumanEntity): Boolean {
|
fun tryEventPreAnvilBypass(event: PrepareAnvilEvent, player: HumanEntity): Boolean {
|
||||||
|
|
@ -135,10 +164,6 @@ object DependencyManager {
|
||||||
// Test excellent enchantments used prepare anvil
|
// Test excellent enchantments used prepare anvil
|
||||||
if (!bypass && (excellentEnchantsCompatibility?.testPrepareAnvil(event) == true)) bypass = true
|
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
|
return bypass
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,8 @@ import org.bukkit.event.Listener
|
||||||
import org.bukkit.event.inventory.PrepareAnvilEvent
|
import org.bukkit.event.inventory.PrepareAnvilEvent
|
||||||
import org.bukkit.inventory.AnvilInventory
|
import org.bukkit.inventory.AnvilInventory
|
||||||
import org.bukkit.inventory.ItemStack
|
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.dependency.DependencyManager
|
||||||
import xyz.alexcrea.cuanvil.util.*
|
import xyz.alexcrea.cuanvil.util.*
|
||||||
import xyz.alexcrea.cuanvil.util.UnitRepairUtil.getRepair
|
import xyz.alexcrea.cuanvil.util.UnitRepairUtil.getRepair
|
||||||
|
|
@ -45,20 +47,30 @@ class PrepareAnvilListener : Listener {
|
||||||
// Should find player
|
// Should find player
|
||||||
val player: HumanEntity = InventoryViewUtil.getInstance().getPlayer(event.view)
|
val player: HumanEntity = InventoryViewUtil.getInstance().getPlayer(event.view)
|
||||||
|
|
||||||
// Test if the event should bypass custom anvil.
|
// Test if custom anvil is bypassed before immutability test
|
||||||
if (DependencyManager.tryEventPreAnvilBypass(event, player)) return
|
if (DependencyManager.earlyTryEventPreAnvilBypass(event, player)) return
|
||||||
|
|
||||||
val inventory = event.inventory
|
val inventory = event.inventory
|
||||||
val first = inventory.getItem(ANVIL_INPUT_LEFT) ?: return
|
val first = inventory.getItem(ANVIL_INPUT_LEFT) ?: return
|
||||||
val second = inventory.getItem(ANVIL_INPUT_RIGHT)
|
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
|
if (!player.hasPermission(CustomAnvil.affectedByPluginPermission)) return
|
||||||
|
|
||||||
// Test custom recipe
|
// Test custom recipe
|
||||||
if(testCustomRecipe(event, inventory, player, first, second)) return
|
if (testCustomRecipe(event, inventory, player, first, second)) return
|
||||||
|
|
||||||
// Test rename lonely item
|
// Test rename lonely item
|
||||||
if(second == null) {
|
if (second == null) {
|
||||||
doRenaming(event, inventory, player, first)
|
doRenaming(event, inventory, player, first)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -70,23 +82,51 @@ class PrepareAnvilListener : Listener {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test for unit repair
|
// Test for unit repair
|
||||||
if(testUnitRepair(event, inventory, player, first, second)) return
|
if (testUnitRepair(event, inventory, player, first, second)) return
|
||||||
|
|
||||||
// Test for lore edit
|
// Test for lore edit
|
||||||
if(testLoreEdit(event, inventory, player, first, second)) return
|
if (testLoreEdit(event, inventory, player, first, second)) return
|
||||||
|
|
||||||
CustomAnvil.log("no anvil fuse type found")
|
CustomAnvil.log("no anvil fuse type found")
|
||||||
event.result = null
|
event.result = null
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
// 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,
|
player: HumanEntity,
|
||||||
first: ItemStack, second: ItemStack?): Boolean {
|
first: ItemStack, second: ItemStack?
|
||||||
|
): Boolean {
|
||||||
val recipe = CustomRecipeUtil.getCustomRecipe(first, second)
|
val recipe = CustomRecipeUtil.getCustomRecipe(first, second)
|
||||||
CustomAnvil.verboseLog("custom recipe not null? ${recipe != null}")
|
CustomAnvil.verboseLog("custom recipe not null? ${recipe != null}")
|
||||||
if(recipe == null) return false
|
if (recipe == null) return false
|
||||||
|
|
||||||
val amount = CustomRecipeUtil.getCustomRecipeAmount(recipe, first, second)
|
val amount = CustomRecipeUtil.getCustomRecipeAmount(recipe, first, second)
|
||||||
|
|
||||||
|
|
@ -94,7 +134,7 @@ class PrepareAnvilListener : Listener {
|
||||||
resultItem.amount *= amount
|
resultItem.amount *= amount
|
||||||
|
|
||||||
event.result = resultItem
|
event.result = resultItem
|
||||||
if(DependencyManager.tryTreatAnvilResult(event, resultItem)) return true
|
if (DependencyManager.tryTreatAnvilResult(event, resultItem)) return true
|
||||||
|
|
||||||
// Maybe add an option on custom craft to ignore/not ignore penalty ??
|
// Maybe add an option on custom craft to ignore/not ignore penalty ??
|
||||||
var xpCost = recipe.xpCostPerCraft * amount
|
var xpCost = recipe.xpCostPerCraft * amount
|
||||||
|
|
@ -105,8 +145,10 @@ class PrepareAnvilListener : Listener {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun doRenaming(event: PrepareAnvilEvent, inventory: AnvilInventory,
|
private fun doRenaming(
|
||||||
player: HumanEntity, first: ItemStack) {
|
event: PrepareAnvilEvent, inventory: AnvilInventory,
|
||||||
|
player: HumanEntity, first: ItemStack
|
||||||
|
) {
|
||||||
val resultItem = first.clone()
|
val resultItem = first.clone()
|
||||||
var anvilCost = handleRename(resultItem, inventory, player)
|
var anvilCost = handleRename(resultItem, inventory, player)
|
||||||
|
|
||||||
|
|
@ -118,7 +160,7 @@ class PrepareAnvilListener : Listener {
|
||||||
}
|
}
|
||||||
|
|
||||||
event.result = resultItem
|
event.result = resultItem
|
||||||
if(DependencyManager.tryTreatAnvilResult(event, resultItem)) return
|
if (DependencyManager.tryTreatAnvilResult(event, resultItem)) return
|
||||||
|
|
||||||
anvilCost += AnvilXpUtil.calculatePenalty(first, null, resultItem, AnvilUseType.RENAME_ONLY)
|
anvilCost += AnvilXpUtil.calculatePenalty(first, null, resultItem, AnvilUseType.RENAME_ONLY)
|
||||||
|
|
||||||
|
|
@ -131,18 +173,20 @@ class PrepareAnvilListener : Listener {
|
||||||
|
|
||||||
var sumCost = 0
|
var sumCost = 0
|
||||||
var useColor = false
|
var useColor = false
|
||||||
if(ConfigOptions.renameColorPossible && inventoryName != null){
|
if (ConfigOptions.renameColorPossible && inventoryName != null) {
|
||||||
val resultString = StringBuilder(inventoryName)
|
val resultString = StringBuilder(inventoryName)
|
||||||
|
|
||||||
useColor = AnvilColorUtil.handleColor(resultString, player,
|
useColor = AnvilColorUtil.handleColor(
|
||||||
|
resultString, player,
|
||||||
ConfigOptions.permissionNeededForColor,
|
ConfigOptions.permissionNeededForColor,
|
||||||
ConfigOptions.allowColorCode, ConfigOptions.allowHexadecimalColor,
|
ConfigOptions.allowColorCode, ConfigOptions.allowHexadecimalColor,
|
||||||
AnvilColorUtil.ColorUseType.RENAME)
|
AnvilColorUtil.ColorUseType.RENAME
|
||||||
|
)
|
||||||
|
|
||||||
if(useColor) {
|
if (useColor) {
|
||||||
inventoryName = resultString.toString()
|
inventoryName = resultString.toString()
|
||||||
|
|
||||||
sumCost+= ConfigOptions.useOfColorCost
|
sumCost += ConfigOptions.useOfColorCost
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -165,9 +209,11 @@ class PrepareAnvilListener : Listener {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun doMerge(event: PrepareAnvilEvent, inventory: AnvilInventory,
|
private fun doMerge(
|
||||||
|
event: PrepareAnvilEvent, inventory: AnvilInventory,
|
||||||
player: HumanEntity,
|
player: HumanEntity,
|
||||||
first: ItemStack, second: ItemStack) {
|
first: ItemStack, second: ItemStack
|
||||||
|
) {
|
||||||
val newEnchants = first.findEnchantments()
|
val newEnchants = first.findEnchantments()
|
||||||
.combineWith(second.findEnchantments(), first, player)
|
.combineWith(second.findEnchantments(), first, player)
|
||||||
val resultItem = first.clone()
|
val resultItem = first.clone()
|
||||||
|
|
@ -195,14 +241,16 @@ class PrepareAnvilListener : Listener {
|
||||||
|
|
||||||
// Finally, we set result
|
// Finally, we set result
|
||||||
event.result = resultItem
|
event.result = resultItem
|
||||||
if(DependencyManager.tryTreatAnvilResult(event, resultItem)) return
|
if (DependencyManager.tryTreatAnvilResult(event, resultItem)) return
|
||||||
|
|
||||||
AnvilXpUtil.setAnvilInvXp(inventory, event.view, player, anvilCost)
|
AnvilXpUtil.setAnvilInvXp(inventory, event.view, player, anvilCost)
|
||||||
}
|
}
|
||||||
|
|
||||||
// return true if there is a valid unit repair with these ingredients
|
// return true if there is a valid unit repair with these ingredients
|
||||||
private fun testUnitRepair(event: PrepareAnvilEvent, inventory: AnvilInventory, player: HumanEntity,
|
private fun testUnitRepair(
|
||||||
first: ItemStack, second: ItemStack): Boolean {
|
event: PrepareAnvilEvent, inventory: AnvilInventory, player: HumanEntity,
|
||||||
|
first: ItemStack, second: ItemStack
|
||||||
|
): Boolean {
|
||||||
val unitRepairAmount = first.getRepair(second) ?: return false
|
val unitRepairAmount = first.getRepair(second) ?: return false
|
||||||
|
|
||||||
val resultItem = first.clone()
|
val resultItem = first.clone()
|
||||||
|
|
@ -222,26 +270,27 @@ class PrepareAnvilListener : Listener {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
event.result = resultItem
|
event.result = resultItem
|
||||||
if(DependencyManager.tryTreatAnvilResult(event, resultItem)) return true
|
if (DependencyManager.tryTreatAnvilResult(event, resultItem)) return true
|
||||||
|
|
||||||
AnvilXpUtil.setAnvilInvXp(inventory, event.view, player, anvilCost)
|
AnvilXpUtil.setAnvilInvXp(inventory, event.view, player, anvilCost)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun testLoreEdit(event: PrepareAnvilEvent, inventory: AnvilInventory, player: HumanEntity,
|
private fun testLoreEdit(
|
||||||
first: ItemStack, second: ItemStack): Boolean {
|
event: PrepareAnvilEvent, inventory: AnvilInventory, player: HumanEntity,
|
||||||
|
first: ItemStack, second: ItemStack
|
||||||
|
): Boolean {
|
||||||
val type = second.type
|
val type = second.type
|
||||||
var result: ItemStack? = null
|
var result: ItemStack? = null
|
||||||
|
|
||||||
val xpCost = AtomicInteger()
|
val xpCost = AtomicInteger()
|
||||||
if(Material.WRITABLE_BOOK == type) {
|
if (Material.WRITABLE_BOOK == type) {
|
||||||
result = AnvilLoreEditUtil.tryLoreEditByBook(player, first, second, xpCost)
|
result = AnvilLoreEditUtil.tryLoreEditByBook(player, first, second, xpCost)
|
||||||
}
|
} else if (Material.PAPER == type) {
|
||||||
else if(Material.PAPER == type) {
|
|
||||||
result = AnvilLoreEditUtil.tryLoreEditByPaper(player, first, second, xpCost)
|
result = AnvilLoreEditUtil.tryLoreEditByPaper(player, first, second, xpCost)
|
||||||
}
|
}
|
||||||
|
|
||||||
if(result == null || first == result) {
|
if (result == null || first == result) {
|
||||||
CustomAnvil.log("lore edit, But input is same as output")
|
CustomAnvil.log("lore edit, But input is same as output")
|
||||||
event.result = null
|
event.result = null
|
||||||
return false
|
return false
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue