mirror of
https://github.com/alexcrea/CustomAnvil.git
synced 2026-06-23 08:14:00 +02:00
25 incompatible with disenchantment (#26)
Ensure compatibility with disenchantment and make it use custom anvil xp settings.
This commit is contained in:
commit
42814237f3
10 changed files with 359 additions and 164 deletions
20
README.md
20
README.md
|
|
@ -47,18 +47,22 @@ under 1.2.0 replace ca prefix by ue and use ue.unsafe. some permission/features
|
|||
anvilconfigreload or carl: Reload every config of this plugin
|
||||
customanvilconfig or configanvil: open a menu for administrator to edit plugin's config in game
|
||||
```
|
||||
### Custom Enchantment Plugins
|
||||
Custom Anvil can be compatible with some custom enchant plugins. \
|
||||
Currently, there is not a lot of compatible plugin
|
||||
### Supported Plugins
|
||||
Custom Anvil can be compatible with some custom enchant and anvil mechanics plugins.
|
||||
|
||||
Here is a list of supported plugins with support status:
|
||||
Here is a list of supported custom enchantment plugins with support status:
|
||||
- [Enchantment²](https://www.spigotmc.org/resources/enchants-squared-the-enchantsplus-rewrite-custom-enchantments-that-act-like-vanilla-ones.86747/):
|
||||
Officially supported by Custom Anvil but still experimental. Automatic configuration.
|
||||
- [EcoEnchant](https://www.spigotmc.org/resources/50-sale-%E2%8C%9B-ecoenchants-%E2%AD%95-250-enchantments-%E2%9C%85-create-custom-enchants-%E2%9C%A8-essentials-cmi-support.79573/):
|
||||
Officially supported by Custom Anvil but still experimental. Need to use /anvilconfigreload or a server restart to add newly added enchantment.
|
||||
Use EcoEnchant restriction system by default.
|
||||
|
||||
If you like Custom Anvil to support a specific custom enchantment plugin.
|
||||
- [EcoEnchant](https://www.spigotmc.org/resources/ecoenchants-%E2%AD%95-250-enchantments-%E2%9C%85-create-custom-enchants-%E2%9C%A8-essentials-cmi-support.79573/):
|
||||
Officially supported by Custom Anvil but still experimental. Need to use /anvilconfigreload or a server restart to add newly added enchantment.
|
||||
Use EcoEnchant restriction system by default.
|
||||
|
||||
Here is a list of supported anvil mechanic plugins with support status:
|
||||
- [Disenchantment](https://www.spigotmc.org/resources/disenchantment-1-21-1-1-20-6-new-book-splitting-mechanics.110741/)
|
||||
Officially supported by Custom Anvil but still experimental. mostly use Custom Anvil xp settings.
|
||||
|
||||
If you like Custom Anvil to support a specific plugin (custom enchant or anvil mechanic).
|
||||
You can ask, but please note implementing compatibility will be considered
|
||||
as low priority as I work for the plugin on my free time for free.
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ plugins {
|
|||
}
|
||||
|
||||
group = "xyz.alexcrea"
|
||||
version = "1.5.5"
|
||||
version = "1.6.0"
|
||||
|
||||
repositories {
|
||||
// EcoEnchants
|
||||
|
|
@ -36,6 +36,9 @@ dependencies {
|
|||
compileOnly("com.willfp:EcoEnchants:12.5.1")
|
||||
compileOnly("com.willfp:eco:6.70.1")
|
||||
|
||||
// Disenchantment
|
||||
compileOnly("cz.kominekjan:Disenchantment:v5.3.1")
|
||||
|
||||
// Include nms
|
||||
implementation(project(":nms:nms-common"))
|
||||
implementation(project(":nms:v1_17R1", configuration = "reobf"))
|
||||
|
|
|
|||
|
|
@ -1,5 +1,14 @@
|
|||
import java.net.URI
|
||||
|
||||
rootProject.name = "CustomAnvil"
|
||||
|
||||
// for Disenchantment dependency
|
||||
sourceControl {
|
||||
gitRepository(URI.create("https://github.com/H7KZ/Disenchantment.git")) {
|
||||
producesModule("cz.kominekjan:Disenchantment")
|
||||
}
|
||||
}
|
||||
|
||||
// NMS subproject
|
||||
include("nms:nms-common")
|
||||
findProject(":nms:nms-common")?.name = "nms-common"
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ package xyz.alexcrea.cuanvil.enchant.wrapped;
|
|||
import me.athlaeos.enchantssquared.enchantments.CustomEnchant;
|
||||
import me.athlaeos.enchantssquared.managers.CustomEnchantManager;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@ import org.bukkit.inventory.ItemStack;
|
|||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import xyz.alexcrea.cuanvil.gui.config.MainConfigGui;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
public class GuiSharedConstant {
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ package io.delilaheve
|
|||
|
||||
import io.delilaheve.util.ConfigOptions
|
||||
import io.delilaheve.util.EnchantmentUtil.combineWith
|
||||
import io.delilaheve.util.EnchantmentUtil.enchantmentName
|
||||
import io.delilaheve.util.ItemUtil.canMergeWith
|
||||
import io.delilaheve.util.ItemUtil.findEnchantments
|
||||
import io.delilaheve.util.ItemUtil.isEnchantedBook
|
||||
|
|
@ -25,11 +24,13 @@ import org.bukkit.event.inventory.PrepareAnvilEvent
|
|||
import org.bukkit.inventory.AnvilInventory
|
||||
import org.bukkit.inventory.InventoryView.Property.REPAIR_COST
|
||||
import org.bukkit.inventory.ItemStack
|
||||
import org.bukkit.inventory.meta.Repairable
|
||||
import xyz.alexcrea.cuanvil.config.ConfigHolder
|
||||
import xyz.alexcrea.cuanvil.dependency.DependencyManager
|
||||
import xyz.alexcrea.cuanvil.dependency.packet.PacketManager
|
||||
import xyz.alexcrea.cuanvil.group.ConflictType
|
||||
import xyz.alexcrea.cuanvil.recipe.AnvilCustomRecipe
|
||||
import xyz.alexcrea.cuanvil.util.AnvilXpUtil.calculatePenalty
|
||||
import xyz.alexcrea.cuanvil.util.AnvilXpUtil.getRightValues
|
||||
import xyz.alexcrea.cuanvil.util.AnvilXpUtil.setAnvilInvXp
|
||||
import xyz.alexcrea.cuanvil.util.UnitRepairUtil.getRepair
|
||||
import java.util.regex.Matcher
|
||||
import java.util.regex.Pattern
|
||||
|
|
@ -43,9 +44,9 @@ class AnvilEventListener(private val packetManager: PacketManager) : Listener {
|
|||
|
||||
companion object {
|
||||
// Anvil's output slot
|
||||
private const val ANVIL_INPUT_LEFT = 0
|
||||
private const val ANVIL_INPUT_RIGHT = 1
|
||||
private const val ANVIL_OUTPUT_SLOT = 2
|
||||
const val ANVIL_INPUT_LEFT = 0
|
||||
const val ANVIL_INPUT_RIGHT = 1
|
||||
const val ANVIL_OUTPUT_SLOT = 2
|
||||
|
||||
// static slot container
|
||||
private val NO_SLOT = SlotContainer(SlotType.NO_SLOT, 0)
|
||||
|
|
@ -57,6 +58,9 @@ class AnvilEventListener(private val packetManager: PacketManager) : Listener {
|
|||
*/
|
||||
@EventHandler(priority = HIGHEST)
|
||||
fun anvilCombineCheck(event: PrepareAnvilEvent) {
|
||||
// Test if the event should bypass custom anvil.
|
||||
if(DependencyManager.tryEventPreAnvilBypass(event)) return
|
||||
|
||||
val inventory = event.inventory
|
||||
val first = inventory.getItem(ANVIL_INPUT_LEFT) ?: return
|
||||
val second = inventory.getItem(ANVIL_INPUT_RIGHT)
|
||||
|
|
@ -75,7 +79,7 @@ class AnvilEventListener(private val packetManager: PacketManager) : Listener {
|
|||
resultItem.amount *= amount
|
||||
|
||||
event.result = resultItem
|
||||
handleAnvilXp(inventory, event, recipe.xpCostPerCraft * amount, true)
|
||||
setAnvilInvXp(inventory, event.view, recipe.xpCostPerCraft * amount, true)
|
||||
|
||||
return
|
||||
}
|
||||
|
|
@ -96,7 +100,7 @@ class AnvilEventListener(private val packetManager: PacketManager) : Listener {
|
|||
|
||||
anvilCost += calculatePenalty(first, null, resultItem)
|
||||
|
||||
handleAnvilXp(inventory, event, anvilCost)
|
||||
setAnvilInvXp(inventory, event.view, anvilCost)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -130,7 +134,7 @@ class AnvilEventListener(private val packetManager: PacketManager) : Listener {
|
|||
// Finally, we set result
|
||||
event.result = resultItem
|
||||
|
||||
handleAnvilXp(inventory, event, anvilCost)
|
||||
setAnvilInvXp(inventory, event.view, anvilCost)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -155,7 +159,7 @@ class AnvilEventListener(private val packetManager: PacketManager) : Listener {
|
|||
}
|
||||
event.result = resultItem
|
||||
|
||||
handleAnvilXp(inventory, event, anvilCost)
|
||||
setAnvilInvXp(inventory, event.view, anvilCost)
|
||||
} else {
|
||||
CustomAnvil.log("no anvil fuse type found")
|
||||
event.result = null
|
||||
|
|
@ -282,9 +286,13 @@ class AnvilEventListener(private val packetManager: PacketManager) : Listener {
|
|||
val player = event.whoClicked as? Player ?: return
|
||||
if (!player.hasPermission(CustomAnvil.affectedByPluginPermission)) return
|
||||
val inventory = event.inventory as? AnvilInventory ?: return
|
||||
|
||||
if (event.rawSlot != ANVIL_OUTPUT_SLOT) {
|
||||
return
|
||||
}
|
||||
// Test if the event should bypass custom anvil.
|
||||
if(DependencyManager.tryClickAnvilResultBypass(event, inventory)) return
|
||||
|
||||
val output = inventory.getItem(ANVIL_OUTPUT_SLOT) ?: return
|
||||
val leftItem = inventory.getItem(ANVIL_INPUT_LEFT) ?: return
|
||||
val rightItem = inventory.getItem(ANVIL_INPUT_RIGHT)
|
||||
|
|
@ -504,96 +512,6 @@ class AnvilEventListener(private val packetManager: PacketManager) : Listener {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to calculate work penalty of anvil work
|
||||
* Also change result work penalty if right item is not null
|
||||
*/
|
||||
private fun calculatePenalty(left: ItemStack, right: ItemStack?, result: ItemStack): Int {
|
||||
return calculatePenalty(left, right, result, false)
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to calculate work penalty of anvil work
|
||||
* Also change result work penalty if right item is not null
|
||||
*/
|
||||
private fun calculatePenalty(left: ItemStack, right: ItemStack?, result: ItemStack, unitRepair: Boolean): Int {
|
||||
// Extracted From https://minecraft.fandom.com/wiki/Anvil_mechanics#Enchantment_equation
|
||||
// Calculate work penalty
|
||||
val leftPenalty = (left.itemMeta as? Repairable)?.repairCost ?: 0
|
||||
val rightPenalty =
|
||||
if (right == null) {
|
||||
0
|
||||
} else {
|
||||
(right.itemMeta as? Repairable)?.repairCost ?: 0
|
||||
}
|
||||
|
||||
// Increase penalty on fusing or unit repair
|
||||
if(right != null || unitRepair){
|
||||
result.itemMeta?.let {
|
||||
(it as? Repairable)?.repairCost = leftPenalty * 2 + 1
|
||||
result.itemMeta = it
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
CustomAnvil.log(
|
||||
"Calculated penalty: " +
|
||||
"leftPenalty: $leftPenalty, " +
|
||||
"rightPenalty: $rightPenalty, " +
|
||||
"result penalty: ${(result.itemMeta as? Repairable)?.repairCost ?: "none"}"
|
||||
)
|
||||
|
||||
return leftPenalty + rightPenalty
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to calculate right enchantment values
|
||||
* it include enchantment placed on final item and conflicting enchantment
|
||||
*/
|
||||
private fun getRightValues(right: ItemStack, result: ItemStack): Int {
|
||||
// Calculate right value and illegal enchant penalty
|
||||
var illegalPenalty = 0
|
||||
var rightValue = 0
|
||||
|
||||
val rightIsFormBook = right.isEnchantedBook()
|
||||
val resultEnchs = result.findEnchantments()
|
||||
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[enchantment.key] = enchantment.value
|
||||
val conflictType = ConfigHolder.CONFLICT_HOLDER.conflictManager.isConflicting(
|
||||
resultEnchsKeys,
|
||||
result,
|
||||
enchantment.key
|
||||
)
|
||||
resultEnchsKeys.remove(enchantment.key)
|
||||
|
||||
if (ConflictType.ENCHANTMENT_CONFLICT == conflictType) {
|
||||
illegalPenalty += ConfigOptions.sacrificeIllegalCost
|
||||
CustomAnvil.verboseLog("Big conflict. Adding illegal price penalty")
|
||||
}
|
||||
continue
|
||||
}
|
||||
// We know "enchantment.key in resultEnchs" true
|
||||
val resultLevel = resultEnchs[enchantment.key]!!
|
||||
|
||||
val enchantmentMultiplier = ConfigOptions.enchantmentValue(enchantment.key, rightIsFormBook)
|
||||
val value = resultLevel * enchantmentMultiplier
|
||||
CustomAnvil.log("Value for ${enchantment.key.enchantmentName} level ${enchantment.value} is $value ($resultLevel * $enchantmentMultiplier)")
|
||||
rightValue += value
|
||||
|
||||
}
|
||||
CustomAnvil.log(
|
||||
"Calculated right values: " +
|
||||
"rightValue: $rightValue, " +
|
||||
"illegalPenalty: $illegalPenalty"
|
||||
)
|
||||
|
||||
return rightValue + illegalPenalty
|
||||
}
|
||||
|
||||
private fun getCustomRecipe (
|
||||
leftItem: ItemStack,
|
||||
rightItem: ItemStack?) : AnvilCustomRecipe? {
|
||||
|
|
@ -638,58 +556,6 @@ class AnvilEventListener(private val packetManager: PacketManager) : Listener {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Display xp needed for the work on the anvil inventory
|
||||
*/
|
||||
private fun handleAnvilXp(
|
||||
inventory: AnvilInventory,
|
||||
event: PrepareAnvilEvent,
|
||||
anvilCost: Int,
|
||||
ignoreRules: Boolean = false
|
||||
) {
|
||||
// Test repair cost limit
|
||||
val finalAnvilCost = if (
|
||||
!ignoreRules &&
|
||||
!ConfigOptions.doRemoveCostLimit &&
|
||||
ConfigOptions.doCapCost) {
|
||||
min(anvilCost, ConfigOptions.maxAnvilCost)
|
||||
} else {
|
||||
anvilCost
|
||||
}
|
||||
|
||||
/* Because Minecraft likes to have the final say in the repair cost displayed
|
||||
* we need to wait for the event to end before overriding it, this ensures that
|
||||
* we have the final say in the process. */
|
||||
CustomAnvil.instance
|
||||
.server
|
||||
.scheduler
|
||||
.runTask(CustomAnvil.instance, Runnable {
|
||||
inventory.maximumRepairCost =
|
||||
if (ConfigOptions.doRemoveCostLimit || ignoreRules)
|
||||
{ Int.MAX_VALUE }
|
||||
else
|
||||
{ ConfigOptions.maxAnvilCost + 1 }
|
||||
|
||||
val player = event.view.player
|
||||
|
||||
inventory.repairCost = finalAnvilCost
|
||||
event.view.setProperty(REPAIR_COST, finalAnvilCost)
|
||||
player.openInventory.setProperty(REPAIR_COST, finalAnvilCost)
|
||||
|
||||
if(player is Player){
|
||||
if(player.gameMode != GameMode.CREATIVE ){
|
||||
val bypassToExpensive = (ConfigOptions.doReplaceTooExpensive) &&
|
||||
(finalAnvilCost >= 40) &&
|
||||
finalAnvilCost < inventory.maximumRepairCost
|
||||
|
||||
packetManager.setInstantBuild(player, bypassToExpensive)
|
||||
}
|
||||
|
||||
player.updateInventory()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
fun onAnvilClose(event: InventoryCloseEvent){
|
||||
val player = event.player
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
package xyz.alexcrea.cuanvil.dependency
|
||||
|
||||
import org.bukkit.Bukkit
|
||||
import org.bukkit.event.inventory.InventoryClickEvent
|
||||
import org.bukkit.event.inventory.PrepareAnvilEvent
|
||||
import org.bukkit.inventory.AnvilInventory
|
||||
import xyz.alexcrea.cuanvil.config.ConfigHolder
|
||||
import xyz.alexcrea.cuanvil.dependency.packet.PacketManager
|
||||
import xyz.alexcrea.cuanvil.dependency.packet.PacketManagerSelector
|
||||
|
|
@ -10,6 +13,7 @@ object DependencyManager {
|
|||
lateinit var packetManager: PacketManager
|
||||
var enchantmentSquaredCompatibility: EnchantmentSquaredDependency? = null
|
||||
var ecoEnchantCompatibility: EcoEnchantDependency? = null
|
||||
var disenchantmentCompatibility: DisenchantmentDependency? = null
|
||||
|
||||
fun loadDependency(){
|
||||
val pluginManager = Bukkit.getPluginManager()
|
||||
|
|
@ -30,6 +34,12 @@ object DependencyManager {
|
|||
ecoEnchantCompatibility!!.disableAnvilListener()
|
||||
}
|
||||
|
||||
// Disenchantment dependency
|
||||
if(pluginManager.isPluginEnabled("Disenchantment")){
|
||||
disenchantmentCompatibility = DisenchantmentDependency()
|
||||
disenchantmentCompatibility!!.redirectListeners()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun handleCompatibilityConfig() {
|
||||
|
|
@ -52,4 +62,20 @@ object DependencyManager {
|
|||
|
||||
}
|
||||
|
||||
fun tryEventPreAnvilBypass(event: PrepareAnvilEvent): Boolean {
|
||||
var bypass = false
|
||||
|
||||
if(disenchantmentCompatibility?.testPrepareAnvil(event) == true) bypass = true
|
||||
|
||||
return bypass
|
||||
}
|
||||
|
||||
fun tryClickAnvilResultBypass(event: InventoryClickEvent, inventory: AnvilInventory): Boolean {
|
||||
var bypass = false
|
||||
|
||||
if(disenchantmentCompatibility?.testAnvilResult(event, inventory) == true) bypass = true
|
||||
|
||||
return bypass
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,123 @@
|
|||
package xyz.alexcrea.cuanvil.dependency
|
||||
|
||||
import cz.kominekjan.disenchantment.events.ItemClickEvent
|
||||
import cz.kominekjan.disenchantment.events.ItemEvent
|
||||
import cz.kominekjan.disenchantment.events.SplitBookClickEvent
|
||||
import cz.kominekjan.disenchantment.events.SplitBookEvent
|
||||
import io.delilaheve.AnvilEventListener
|
||||
import io.delilaheve.CustomAnvil
|
||||
import org.bukkit.event.inventory.InventoryClickEvent
|
||||
import org.bukkit.event.inventory.PrepareAnvilEvent
|
||||
import org.bukkit.inventory.AnvilInventory
|
||||
import org.bukkit.inventory.ItemStack
|
||||
import org.bukkit.plugin.RegisteredListener
|
||||
import xyz.alexcrea.cuanvil.util.AnvilXpUtil
|
||||
|
||||
class DisenchantmentDependency {
|
||||
|
||||
init {
|
||||
CustomAnvil.instance.logger.info("Disenchantment Detected !")
|
||||
}
|
||||
|
||||
private lateinit var splitEvent: SplitBookEvent
|
||||
private lateinit var itemEvent: ItemEvent
|
||||
|
||||
private lateinit var splitBookClickEvent: SplitBookClickEvent
|
||||
private lateinit var itemClickEvent: ItemClickEvent
|
||||
|
||||
fun redirectListeners() {
|
||||
|
||||
val toUnregister = ArrayList<RegisteredListener>()
|
||||
// get required PrepareAnvilEvent listener
|
||||
for (registeredListener in PrepareAnvilEvent.getHandlerList().registeredListeners) {
|
||||
val listener = registeredListener.listener
|
||||
|
||||
if(listener is SplitBookEvent){
|
||||
this.splitEvent = listener
|
||||
toUnregister.add(registeredListener)
|
||||
}
|
||||
|
||||
if(listener is ItemEvent){
|
||||
itemEvent = listener
|
||||
toUnregister.add(registeredListener)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (listener in toUnregister) {
|
||||
PrepareAnvilEvent.getHandlerList().unregister(listener)
|
||||
}
|
||||
toUnregister.clear()
|
||||
|
||||
// get required InventoryClickEvent listener
|
||||
for (registeredListener in InventoryClickEvent.getHandlerList().registeredListeners) {
|
||||
val listener = registeredListener.listener
|
||||
|
||||
if(listener is SplitBookClickEvent){
|
||||
splitBookClickEvent = listener
|
||||
toUnregister.add(registeredListener)
|
||||
}
|
||||
|
||||
if(listener is ItemClickEvent){
|
||||
itemClickEvent = listener
|
||||
toUnregister.add(registeredListener)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (listener in toUnregister) {
|
||||
InventoryClickEvent.getHandlerList().unregister(listener)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun testPrepareAnvil(event: PrepareAnvilEvent): Boolean {
|
||||
val previousResult = event.result
|
||||
event.result = null
|
||||
|
||||
// Test if event change the result
|
||||
itemEvent.onDisenchantmentEvent(event)
|
||||
|
||||
if(event.result != null) {
|
||||
CustomAnvil.log("Detected pre anvil item extract bypass.")
|
||||
AnvilXpUtil.setAnvilInvXp(event.inventory, event.view, event.inventory.repairCost)
|
||||
return true
|
||||
}
|
||||
|
||||
splitEvent.onDisenchantmentEvent(event)
|
||||
if(event.result != null) {
|
||||
CustomAnvil.log("Detected pre anvil split enchant bypass.")
|
||||
AnvilXpUtil.setAnvilInvXp(event.inventory, event.view, event.inventory.repairCost)
|
||||
return true
|
||||
}
|
||||
|
||||
event.result = previousResult
|
||||
return false
|
||||
}
|
||||
|
||||
fun testAnvilResult(event: InventoryClickEvent, inventory: AnvilInventory): Boolean {
|
||||
val previousResultSlot = inventory.getItem(AnvilEventListener.ANVIL_OUTPUT_SLOT)?.clone()
|
||||
|
||||
// Test event if change the result
|
||||
itemClickEvent.onDisenchantmentClickEvent(event)
|
||||
if(!testAnvilInventoryChange(inventory, previousResultSlot) || event.isCancelled) {
|
||||
CustomAnvil.log("Detected anvil click item extract bypass.")
|
||||
return true
|
||||
}
|
||||
|
||||
splitBookClickEvent.onDisenchantmentClickEvent(event)
|
||||
if(!testAnvilInventoryChange(inventory, previousResultSlot) || event.isCancelled) {
|
||||
CustomAnvil.log("Detected anvil click split enchant bypass.")
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private fun testAnvilInventoryChange(inventory: AnvilInventory, previous: ItemStack?): Boolean {
|
||||
val currentResult = inventory.getItem(AnvilEventListener.ANVIL_OUTPUT_SLOT)
|
||||
|
||||
return currentResult == previous
|
||||
}
|
||||
|
||||
}
|
||||
163
src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilXpUtil.kt
Normal file
163
src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilXpUtil.kt
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
package xyz.alexcrea.cuanvil.util
|
||||
|
||||
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.entity.Player
|
||||
import org.bukkit.inventory.AnvilInventory
|
||||
import org.bukkit.inventory.InventoryView
|
||||
import org.bukkit.inventory.InventoryView.Property.REPAIR_COST
|
||||
import org.bukkit.inventory.ItemStack
|
||||
import org.bukkit.inventory.meta.Repairable
|
||||
import xyz.alexcrea.cuanvil.config.ConfigHolder
|
||||
import xyz.alexcrea.cuanvil.dependency.DependencyManager
|
||||
import xyz.alexcrea.cuanvil.group.ConflictType
|
||||
import kotlin.math.min
|
||||
|
||||
object AnvilXpUtil {
|
||||
|
||||
/**
|
||||
* Display xp needed for the work on the anvil inventory
|
||||
*/
|
||||
fun setAnvilInvXp(
|
||||
inventory: AnvilInventory,
|
||||
view: InventoryView,
|
||||
anvilCost: Int,
|
||||
ignoreRules: Boolean = false
|
||||
) {
|
||||
// Test repair cost limit
|
||||
val finalAnvilCost = if (
|
||||
!ignoreRules &&
|
||||
!ConfigOptions.doRemoveCostLimit &&
|
||||
ConfigOptions.doCapCost) {
|
||||
min(anvilCost, ConfigOptions.maxAnvilCost)
|
||||
} else {
|
||||
anvilCost
|
||||
}
|
||||
|
||||
/* Because Minecraft likes to have the final say in the repair cost displayed
|
||||
* we need to wait for the event to end before overriding it, this ensures that
|
||||
* we have the final say in the process. */
|
||||
CustomAnvil.instance
|
||||
.server
|
||||
.scheduler
|
||||
.runTask(CustomAnvil.instance, Runnable {
|
||||
inventory.maximumRepairCost =
|
||||
if (ConfigOptions.doRemoveCostLimit || ignoreRules)
|
||||
{ Int.MAX_VALUE }
|
||||
else
|
||||
{ ConfigOptions.maxAnvilCost + 1 }
|
||||
|
||||
val player = view.player
|
||||
|
||||
inventory.repairCost = finalAnvilCost
|
||||
view.setProperty(REPAIR_COST, finalAnvilCost)
|
||||
player.openInventory.setProperty(REPAIR_COST, finalAnvilCost)
|
||||
|
||||
if(player is Player){
|
||||
if(player.gameMode != GameMode.CREATIVE ){
|
||||
val bypassToExpensive = (ConfigOptions.doReplaceTooExpensive) &&
|
||||
(finalAnvilCost >= 40) &&
|
||||
finalAnvilCost < inventory.maximumRepairCost
|
||||
|
||||
DependencyManager.packetManager.setInstantBuild(player, bypassToExpensive)
|
||||
}
|
||||
|
||||
player.updateInventory()
|
||||
}
|
||||
})
|
||||
}
|
||||
/**
|
||||
* Function to calculate work penalty of anvil work
|
||||
* Also change result work penalty if right item is not null
|
||||
*/
|
||||
fun calculatePenalty(left: ItemStack, right: ItemStack?, result: ItemStack): Int {
|
||||
return calculatePenalty(left, right, result, false)
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to calculate work penalty of anvil work
|
||||
* Also change result work penalty if right item is not null
|
||||
*/
|
||||
fun calculatePenalty(left: ItemStack, right: ItemStack?, result: ItemStack, unitRepair: Boolean): Int {
|
||||
// Extracted From https://minecraft.fandom.com/wiki/Anvil_mechanics#Enchantment_equation
|
||||
// Calculate work penalty
|
||||
val leftPenalty = (left.itemMeta as? Repairable)?.repairCost ?: 0
|
||||
val rightPenalty =
|
||||
if (right == null) {
|
||||
0
|
||||
} else {
|
||||
(right.itemMeta as? Repairable)?.repairCost ?: 0
|
||||
}
|
||||
|
||||
// Increase penalty on fusing or unit repair
|
||||
if(right != null || unitRepair){
|
||||
result.itemMeta?.let {
|
||||
(it as? Repairable)?.repairCost = leftPenalty * 2 + 1
|
||||
result.itemMeta = it
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
CustomAnvil.log(
|
||||
"Calculated penalty: " +
|
||||
"leftPenalty: $leftPenalty, " +
|
||||
"rightPenalty: $rightPenalty, " +
|
||||
"result penalty: ${(result.itemMeta as? Repairable)?.repairCost ?: "none"}"
|
||||
)
|
||||
|
||||
return leftPenalty + rightPenalty
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to calculate right enchantment values
|
||||
* it include enchantment placed on final item and conflicting enchantment
|
||||
*/
|
||||
fun getRightValues(right: ItemStack, result: ItemStack): Int {
|
||||
// Calculate right value and illegal enchant penalty
|
||||
var illegalPenalty = 0
|
||||
var rightValue = 0
|
||||
|
||||
val rightIsFormBook = right.isEnchantedBook()
|
||||
val resultEnchs = result.findEnchantments()
|
||||
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[enchantment.key] = enchantment.value
|
||||
val conflictType = ConfigHolder.CONFLICT_HOLDER.conflictManager.isConflicting(
|
||||
resultEnchsKeys,
|
||||
result,
|
||||
enchantment.key
|
||||
)
|
||||
resultEnchsKeys.remove(enchantment.key)
|
||||
|
||||
if (ConflictType.ENCHANTMENT_CONFLICT == conflictType) {
|
||||
illegalPenalty += ConfigOptions.sacrificeIllegalCost
|
||||
CustomAnvil.verboseLog("Big conflict. Adding illegal price penalty")
|
||||
}
|
||||
continue
|
||||
}
|
||||
// We know "enchantment.key in resultEnchs" true
|
||||
val resultLevel = resultEnchs[enchantment.key]!!
|
||||
|
||||
val enchantmentMultiplier = ConfigOptions.enchantmentValue(enchantment.key, rightIsFormBook)
|
||||
val value = resultLevel * enchantmentMultiplier
|
||||
CustomAnvil.log("Value for ${enchantment.key.enchantmentName} level ${enchantment.value} is $value ($resultLevel * $enchantmentMultiplier)")
|
||||
rightValue += value
|
||||
|
||||
}
|
||||
CustomAnvil.log(
|
||||
"Calculated right values: " +
|
||||
"rightValue: $rightValue, " +
|
||||
"illegalPenalty: $illegalPenalty"
|
||||
)
|
||||
|
||||
return rightValue + illegalPenalty
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
main: io.delilaheve.CustomAnvil
|
||||
name: CustomAnvil
|
||||
prefix: "Custom Anvil"
|
||||
version: 1.5.5
|
||||
version: 1.6.0
|
||||
description: Allow to customise anvil mechanics
|
||||
api-version: 1.16
|
||||
load: POSTWORLD
|
||||
|
|
@ -53,6 +53,7 @@ permissions:
|
|||
softdepend:
|
||||
- UnsafeEnchantsPlus
|
||||
- ProtocolLib
|
||||
- Disenchantment
|
||||
- EnchantsSquared
|
||||
- EcoEnchants
|
||||
- eco
|
||||
Loading…
Add table
Add a link
Reference in a new issue