mirror of
https://github.com/alexcrea/CustomAnvil.git
synced 2026-06-24 00:26:16 +02:00
add xp rename cost and fix non vanilla anvil beavior. but keep some protection to avoid useless fuse.
This commit is contained in:
parent
760cdef6ad
commit
bd28c5b71c
4 changed files with 115 additions and 68 deletions
|
|
@ -29,6 +29,8 @@ class AnvilEventListener : Listener {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
// Anvil's output slot
|
// 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
|
private const val ANVIL_OUTPUT_SLOT = 2
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -38,19 +40,15 @@ class AnvilEventListener : Listener {
|
||||||
@EventHandler(priority = HIGHEST)
|
@EventHandler(priority = HIGHEST)
|
||||||
fun anvilCombineCheck(event: PrepareAnvilEvent) {
|
fun anvilCombineCheck(event: PrepareAnvilEvent) {
|
||||||
val inventory = event.inventory
|
val inventory = event.inventory
|
||||||
val first = inventory.getItem(0) ?: return
|
val first = inventory.getItem(ANVIL_INPUT_LEFT) ?: return
|
||||||
val second = inventory.getItem(1) ?: return
|
val second = inventory.getItem(ANVIL_INPUT_RIGHT) ?: return
|
||||||
if (first.canMergeWith(second)) {
|
if (first.canMergeWith(second)) {
|
||||||
// Try to find player
|
// Try to find player
|
||||||
val player = event.view.player
|
val player = event.view.player
|
||||||
|
|
||||||
val newEnchants = first.findEnchantments()
|
val newEnchants = first.findEnchantments()
|
||||||
.combineWith(second.findEnchantments(),player)
|
.combineWith(second.findEnchantments(), first.type, player)
|
||||||
val resultItem = first.clone()
|
val resultItem = first.clone()
|
||||||
resultItem.itemMeta?.let {
|
|
||||||
it.setDisplayName(inventory.renameText)
|
|
||||||
resultItem.itemMeta = it
|
|
||||||
}
|
|
||||||
resultItem.setEnchantmentsUnsafe(newEnchants)
|
resultItem.setEnchantmentsUnsafe(newEnchants)
|
||||||
var repairCost: Int
|
var repairCost: Int
|
||||||
if (!first.isBook() && !second.isBook()) {
|
if (!first.isBook() && !second.isBook()) {
|
||||||
|
|
@ -61,17 +59,26 @@ class AnvilEventListener : Listener {
|
||||||
repairCost = resultItem.repairCost
|
repairCost = resultItem.repairCost
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test if nothing change and stop.
|
||||||
|
if(first == resultItem){
|
||||||
|
event.result = null
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rename item and add renaming cost
|
||||||
|
resultItem.itemMeta?.let {
|
||||||
|
if(!it.displayName.contentEquals(inventory.renameText)){
|
||||||
|
it.setDisplayName(inventory.renameText)
|
||||||
|
resultItem.itemMeta = it
|
||||||
|
repairCost += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (ConfigOptions.limitRepairCost) {
|
if (ConfigOptions.limitRepairCost) {
|
||||||
repairCost = min(repairCost, ConfigOptions.limitRepairValue)
|
repairCost = min(repairCost, ConfigOptions.limitRepairValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set object only if allowed
|
|
||||||
if(itemAllowed(resultItem,player)){
|
|
||||||
event.result = resultItem
|
event.result = resultItem
|
||||||
} else{
|
|
||||||
event.result = null
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Because Minecraft likes to have the final say in the repair cost displayed
|
/* 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 need to wait for the event to end before overriding it, this ensures that
|
||||||
|
|
@ -94,29 +101,16 @@ class AnvilEventListener : Listener {
|
||||||
*/
|
*/
|
||||||
@EventHandler(ignoreCancelled = true)
|
@EventHandler(ignoreCancelled = true)
|
||||||
fun anvilExtractionCheck(event: InventoryClickEvent) {
|
fun anvilExtractionCheck(event: InventoryClickEvent) {
|
||||||
val player = event.whoClicked as? Player ?: return
|
//val player = event.whoClicked as? Player ?: return
|
||||||
val inventory = event.inventory as? AnvilInventory ?: return
|
val inventory = event.inventory as? AnvilInventory ?: return
|
||||||
if (event.rawSlot != ANVIL_OUTPUT_SLOT) { return }
|
if (event.rawSlot != ANVIL_OUTPUT_SLOT) { return }
|
||||||
val output = inventory.getItem(ANVIL_OUTPUT_SLOT) ?: return
|
val output = inventory.getItem(ANVIL_OUTPUT_SLOT) ?: return
|
||||||
// Should be true most of the time
|
// Is true if there was no change. probably when there are conflict
|
||||||
// But if permissions change in the anvil it can be false
|
if(output == inventory.getItem(ANVIL_INPUT_LEFT)){
|
||||||
if(!itemAllowed(output,player)){
|
|
||||||
event.result = Event.Result.DENY
|
event.result = Event.Result.DENY
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
event.result = Event.Result.ALLOW
|
event.result = Event.Result.ALLOW
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun itemAllowed(item: ItemStack, player: HumanEntity): Boolean{
|
|
||||||
if(player.hasPermission(UnsafeEnchants.bypassFusePermission)) return true
|
|
||||||
|
|
||||||
if(player.hasPermission(UnsafeEnchants.unsafePermission)){
|
|
||||||
if(UnsafeEnchants.conflictManager.isConflicting(item))
|
|
||||||
return false
|
|
||||||
}else if (item.findEnchantments().hasConflicts()){
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package io.delilaheve.util
|
package io.delilaheve.util
|
||||||
|
|
||||||
import io.delilaheve.UnsafeEnchants
|
import io.delilaheve.UnsafeEnchants
|
||||||
|
import org.bukkit.Material
|
||||||
import org.bukkit.enchantments.Enchantment
|
import org.bukkit.enchantments.Enchantment
|
||||||
import org.bukkit.entity.HumanEntity
|
import org.bukkit.entity.HumanEntity
|
||||||
import kotlin.math.max
|
import kotlin.math.max
|
||||||
|
|
@ -21,30 +22,45 @@ object EnchantmentUtil {
|
||||||
* Combine 2 sets of enchantments according to our configuration
|
* Combine 2 sets of enchantments according to our configuration
|
||||||
*/
|
*/
|
||||||
fun Map<Enchantment, Int>.combineWith(
|
fun Map<Enchantment, Int>.combineWith(
|
||||||
other: Map<Enchantment, Int>, player: HumanEntity
|
other: Map<Enchantment, Int>,
|
||||||
|
mat: Material,
|
||||||
|
player: HumanEntity
|
||||||
) = mutableMapOf<Enchantment, Int>().apply {
|
) = mutableMapOf<Enchantment, Int>().apply {
|
||||||
putAll(this@combineWith)
|
putAll(this@combineWith)
|
||||||
other.forEach { (enchantment, level) ->
|
other.forEach { (enchantment, level) ->
|
||||||
when {
|
|
||||||
// Enchantment not yet in result list
|
// Enchantment not yet in result list
|
||||||
!containsKey(enchantment) -> {
|
if (!containsKey(enchantment)) {
|
||||||
// Add the enchantment if it doesn't have conflicts, or, if we're allowing unsafe enchantments
|
if(player.hasPermission(UnsafeEnchants.unsafePermission)){
|
||||||
if (!keys.any { enchantment.conflictsWith(it) } || ConfigOptions.allowUnsafe) {
|
// Add the enchantment if it doesn't have conflicts, or, if player is allowed to bypass enchantment restrictions
|
||||||
|
this[enchantment] = level
|
||||||
|
if(!player.hasPermission(UnsafeEnchants.bypassFusePermission) &&
|
||||||
|
UnsafeEnchants.conflictManager.isConflicting(this.keys,mat,enchantment)){
|
||||||
|
this.remove(enchantment)
|
||||||
|
}
|
||||||
|
}else if(!keys.any { enchantment.conflictsWith(it) }){
|
||||||
|
|
||||||
this[enchantment] = level
|
this[enchantment] = level
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Enchantment already in result list...
|
// Enchantment already in result list
|
||||||
else -> when {
|
else{
|
||||||
|
// ... and they are conflicting
|
||||||
|
if(UnsafeEnchants.conflictManager.isConflicting(this.keys,mat,enchantment)
|
||||||
|
&& !player.hasPermission(UnsafeEnchants.bypassFusePermission)){
|
||||||
|
return@forEach
|
||||||
|
}
|
||||||
|
|
||||||
// ... and they're not the same level
|
// ... and they're not the same level
|
||||||
this[enchantment] != other[enchantment] -> {
|
if(this[enchantment] != other[enchantment]){
|
||||||
val newLevel = max(this[enchantment] ?: 0, other[enchantment] ?: 0)
|
val newLevel = max(this[enchantment] ?: 0, other[enchantment] ?: 0)
|
||||||
// apply the greater of the two if non-zero
|
// apply the greater of the two if non-zero
|
||||||
if (newLevel > 0) { this[enchantment] = newLevel }
|
if (newLevel > 0) { this[enchantment] = newLevel }
|
||||||
}
|
}
|
||||||
// ... and they're the same level
|
// ... and they're the same level
|
||||||
else -> {
|
else {
|
||||||
// try to increase the enchantment level by 1
|
// try to increase the enchantment level by 1
|
||||||
var newLevel = this[enchantment]?.plus(1) ?: 0
|
var newLevel = this[enchantment]!! +1
|
||||||
|
// Get max level or 255 if player can bypass
|
||||||
val maxLevel = if(player.hasPermission(UnsafeEnchants.bypassLevelPermission)){
|
val maxLevel = if(player.hasPermission(UnsafeEnchants.bypassLevelPermission)){
|
||||||
255
|
255
|
||||||
}else{
|
}else{
|
||||||
|
|
@ -56,7 +72,7 @@ object EnchantmentUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if a set of enchantments has any conflicts
|
* Check if a set of enchantments has any conflicts
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
package xyz.alexcrea.group
|
package xyz.alexcrea.group
|
||||||
|
|
||||||
import io.delilaheve.util.ItemUtil.findEnchantments
|
import io.delilaheve.util.ItemUtil.findEnchantments
|
||||||
|
import org.bukkit.Material
|
||||||
import org.bukkit.enchantments.Enchantment
|
import org.bukkit.enchantments.Enchantment
|
||||||
import org.bukkit.inventory.ItemStack
|
import org.bukkit.inventory.ItemStack
|
||||||
|
|
||||||
class EnchantConflictGroup(val cantConflict: AbstractMaterialGroup, val minBeforeBlock: Int){
|
class EnchantConflictGroup(private val cantConflict: AbstractMaterialGroup, private val minBeforeBlock: Int){
|
||||||
|
|
||||||
private val enchantments = HashSet<Enchantment>()
|
private val enchantments = HashSet<Enchantment>()
|
||||||
|
|
||||||
|
|
@ -12,7 +13,7 @@ class EnchantConflictGroup(val cantConflict: AbstractMaterialGroup, val minBefor
|
||||||
enchantments.add(ench)
|
enchantments.add(ench)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun allow(item: ItemStack) : Boolean{
|
fun allowed(item: ItemStack) : Boolean{
|
||||||
if(enchantments.size < minBeforeBlock){
|
if(enchantments.size < minBeforeBlock){
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
@ -21,22 +22,27 @@ class EnchantConflictGroup(val cantConflict: AbstractMaterialGroup, val minBefor
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return allowed(item.enchantments.keys, item.type)
|
||||||
|
}
|
||||||
|
fun allowed(enchants: Set<Enchantment>, mat: Material) : Boolean{
|
||||||
|
if(cantConflict.contain(mat)){
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// Count the amount of enchantment that are in the list
|
// Count the amount of enchantment that are in the list
|
||||||
var enchantAmount = 0
|
var enchantAmount = 0
|
||||||
for (enchantment in item.findEnchantments().keys) {
|
for (enchantment in enchants) {
|
||||||
if(enchantment !in enchantments) continue
|
if(enchantment !in enchantments) continue
|
||||||
if(++enchantAmount > minBeforeBlock){
|
if(++enchantAmount > minBeforeBlock){
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isEnchantEmpty(): Boolean {
|
fun getEnchants(): HashSet<Enchantment> {
|
||||||
return enchantments.size == 0
|
return enchantments
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package xyz.alexcrea.group
|
package xyz.alexcrea.group
|
||||||
|
|
||||||
import io.delilaheve.UnsafeEnchants
|
import io.delilaheve.UnsafeEnchants
|
||||||
|
import org.bukkit.Material
|
||||||
import org.bukkit.NamespacedKey
|
import org.bukkit.NamespacedKey
|
||||||
import org.bukkit.configuration.ConfigurationSection
|
import org.bukkit.configuration.ConfigurationSection
|
||||||
import org.bukkit.configuration.file.YamlConfiguration
|
import org.bukkit.configuration.file.YamlConfiguration
|
||||||
|
|
@ -26,23 +27,34 @@ class EnchantConflictManager {
|
||||||
private const val DEFAULT_GROUP_NAME = "joinedGroup"
|
private const val DEFAULT_GROUP_NAME = "joinedGroup"
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var conflictList: ArrayList<EnchantConflictGroup>
|
private lateinit var conflictMap: HashMap<Enchantment, ArrayList<EnchantConflictGroup>>
|
||||||
|
|
||||||
// Read and prepare all conflict
|
// Read and prepare all conflict
|
||||||
fun prepareConflicts(config: YamlConfiguration, itemManager: ItemGroupManager){
|
fun prepareConflicts(config: YamlConfiguration, itemManager: ItemGroupManager){
|
||||||
conflictList = ArrayList()
|
conflictMap = HashMap()
|
||||||
|
|
||||||
val keys = config.getKeys(false)
|
val keys = config.getKeys(false)
|
||||||
for (key in keys) {
|
for (key in keys) {
|
||||||
val section = config.getConfigurationSection(key)!!
|
val section = config.getConfigurationSection(key)!!
|
||||||
val conflict = createConflict(section,itemManager,key)
|
val conflict = createConflict(section,itemManager,key)
|
||||||
if(conflict != null){
|
if(conflict != null){
|
||||||
conflictList.add(conflict)
|
addToMap(conflict)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the conflict to the map
|
||||||
|
private fun addToMap(conflict: EnchantConflictGroup){
|
||||||
|
conflict.getEnchants().forEach{ enchant ->
|
||||||
|
if(!conflictMap.containsKey(enchant)){
|
||||||
|
conflictMap[enchant] = ArrayList()
|
||||||
|
}
|
||||||
|
conflictMap[enchant]!!.add(conflict)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// create and read a conflict from a yaml section
|
// create and read a conflict from a yaml section
|
||||||
private fun createConflict(section: ConfigurationSection,
|
private fun createConflict(section: ConfigurationSection,
|
||||||
itemManager: ItemGroupManager,
|
itemManager: ItemGroupManager,
|
||||||
|
|
@ -64,7 +76,7 @@ class EnchantConflictManager {
|
||||||
}
|
}
|
||||||
conflict.addEnchantment(enchant)
|
conflict.addEnchantment(enchant)
|
||||||
}
|
}
|
||||||
if(conflict.isEnchantEmpty()){
|
if(conflict.getEnchants().size == 0){
|
||||||
if(!futureUse){
|
if(!futureUse){
|
||||||
UnsafeEnchants.instance.logger.warning("Conflict $conflictName do not have valid enchantment, it will not work")
|
UnsafeEnchants.instance.logger.warning("Conflict $conflictName do not have valid enchantment, it will not work")
|
||||||
}
|
}
|
||||||
|
|
@ -112,8 +124,27 @@ class EnchantConflictManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun isConflicting(item: ItemStack): Boolean{
|
fun isConflicting(item: ItemStack): Boolean{
|
||||||
|
val toTest = HashSet<EnchantConflictGroup>()
|
||||||
|
item.enchantments.forEach{enchant ->
|
||||||
|
val conflictList = conflictMap[enchant.key]
|
||||||
|
if(conflictList != null){
|
||||||
|
toTest.addAll(conflictList)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (conflict in toTest) {
|
||||||
|
if(!conflict.allowed(item)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
fun isConflicting(base: Set<Enchantment>,mat: Material, newEnchant: Enchantment): Boolean{
|
||||||
|
val conflictList = conflictMap[newEnchant] ?: return false
|
||||||
|
|
||||||
for (conflict in conflictList) {
|
for (conflict in conflictList) {
|
||||||
if(!conflict.allow(item)) {
|
if(!conflict.allowed(base,mat)) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue