custom conflict now work.

This commit is contained in:
alexcrea 2024-02-01 19:38:49 +01:00
parent baa0c064da
commit 9f35c1a98d
6 changed files with 201 additions and 26 deletions

View file

@ -9,6 +9,7 @@ import io.delilaheve.util.ItemUtil.isBook
import io.delilaheve.util.ItemUtil.repairCost import io.delilaheve.util.ItemUtil.repairCost
import io.delilaheve.util.ItemUtil.repairFrom import io.delilaheve.util.ItemUtil.repairFrom
import io.delilaheve.util.ItemUtil.setEnchantmentsUnsafe import io.delilaheve.util.ItemUtil.setEnchantmentsUnsafe
import org.bukkit.entity.HumanEntity
import org.bukkit.entity.Player import org.bukkit.entity.Player
import org.bukkit.event.Event import org.bukkit.event.Event
import org.bukkit.event.EventHandler import org.bukkit.event.EventHandler
@ -18,6 +19,7 @@ import org.bukkit.event.inventory.InventoryClickEvent
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.InventoryView.Property.REPAIR_COST import org.bukkit.inventory.InventoryView.Property.REPAIR_COST
import org.bukkit.inventory.ItemStack
import org.bukkit.permissions.Permission import org.bukkit.permissions.Permission
import kotlin.math.min import kotlin.math.min
@ -63,7 +65,17 @@ class AnvilEventListener : Listener {
if (ConfigOptions.limitRepairCost) { if (ConfigOptions.limitRepairCost) {
repairCost = min(repairCost, ConfigOptions.limitRepairValue) repairCost = min(repairCost, ConfigOptions.limitRepairValue)
} }
event.result = resultItem
// Try to find player
val player = event.view.player
// Set object only if allowed
if(itemAllowed(resultItem,player)){
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
* we have the final say in the process. */ * we have the final say in the process. */
@ -87,16 +99,27 @@ class AnvilEventListener : Listener {
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
val output = inventory.getItem(ANVIL_OUTPUT_SLOT) ?: return
if(!player.hasPermission(bypassPermission)){
if (output.findEnchantments().hasConflicts() && !player.hasPermission(requirePermission)) {
return
}
}
if (event.rawSlot != ANVIL_OUTPUT_SLOT) { return } if (event.rawSlot != ANVIL_OUTPUT_SLOT) { return }
val output = inventory.getItem(ANVIL_OUTPUT_SLOT) ?: return
// Should be true most of the time
// But if permissions change in the anvil it can be false
if(!itemAllowed(output,player)){
event.result = Event.Result.DENY
return
}
event.result = Event.Result.ALLOW event.result = Event.Result.ALLOW
} }
private fun itemAllowed(item: ItemStack, player: HumanEntity): Boolean{
if(!player.hasPermission(bypassPermission)){
if(player.hasPermission(requirePermission)){
if(UnsafeEnchants.conflictManager.isConflicting(item))
return false
} else if(item.findEnchantments().hasConflicts())
return false
}
return true
}
} }

View file

@ -1,9 +1,13 @@
package io.delilaheve package io.delilaheve
import io.delilaheve.util.ConfigOptions import io.delilaheve.util.ConfigOptions
import org.bukkit.Bukkit
import org.bukkit.configuration.file.YamlConfiguration import org.bukkit.configuration.file.YamlConfiguration
import org.bukkit.plugin.java.JavaPlugin import org.bukkit.plugin.java.JavaPlugin
import xyz.alexcrea.group.EnchantConflictManager
import xyz.alexcrea.group.ItemGroupManager import xyz.alexcrea.group.ItemGroupManager
import java.io.File
import java.io.FileReader
/** /**
* Bukkit/Spigot/Paper plugin to alter enchantment max * Bukkit/Spigot/Paper plugin to alter enchantment max
@ -18,11 +22,13 @@ class UnsafeEnchants : JavaPlugin() {
const val unsafeBypassPermission = "ue.unsafe_all" const val unsafeBypassPermission = "ue.unsafe_all"
// Item Grouping Configuration file name // Item Grouping Configuration file name
const val itemGroupingConfigName = "item_groups.yml" const val itemGroupingConfigName = "item_groups.yml"
// Conflict Configuration file name
const val enchantConflicConfigName = "enchant_conflict.yml"
// Current plugin instance // Current plugin instance
lateinit var instance: UnsafeEnchants lateinit var instance: UnsafeEnchants
// Current item grouping configuration instance // Current item grouping configuration instance
lateinit var itemGroups: ItemGroupManager lateinit var conflictManager: EnchantConflictManager
/** /**
* Logging handler * Logging handler
@ -41,24 +47,50 @@ class UnsafeEnchants : JavaPlugin() {
instance = this instance = this
saveDefaultConfig() saveDefaultConfig()
// Save default material grouping config
saveResource(itemGroupingConfigName,false)
// Load material grouping config // Load material grouping config
val itemGroupConfig = YamlConfiguration() val itemGroupConfig = reloadResource(itemGroupingConfigName) ?: return
val configReader = this.getTextResource(itemGroupingConfigName)
if(configReader == null){
logger.severe("could no load item grouping configuration")
}else{
itemGroupConfig.load(configReader)
}
// Read material groups from config // Read material groups from config
itemGroups = ItemGroupManager() val itemGroupsManager = ItemGroupManager()
itemGroups.prepareGroups(itemGroupConfig) itemGroupsManager.prepareGroups(itemGroupConfig)
// Load enchantment conflicts config
val conflictConfig = reloadResource(enchantConflicConfigName) ?: return
// Read conflicts from config and material group manager
conflictManager = EnchantConflictManager()
conflictManager.prepareConflicts(conflictConfig,itemGroupsManager)
server.pluginManager.registerEvents( server.pluginManager.registerEvents(
AnvilEventListener(), AnvilEventListener(),
this this
) )
}
private fun reloadResource(resourceName: String,
hardFailSafe:Boolean = true): YamlConfiguration?{
// Save default resource
val file = File(dataFolder,resourceName)
if(!file.exists()){
saveResource(resourceName,false)
}
// Load resource
val yamlConfig = YamlConfiguration()
try {
val configReader = FileReader(file)
yamlConfig.load(configReader)
} catch (test: Exception){
if(hardFailSafe){
// This is important and may impact gameplay if it does not load.
// Failsafe is to stop the plugin
logger.severe("Resource $resourceName Could not be load or reload.")
logger.severe("Disabling plugin.")
Bukkit.getPluginManager().disablePlugin(this)
}else{
logger.warning("Resource $resourceName Could not be load or reload.")
}
return null
}
return yamlConfig
} }
} }

View file

@ -62,7 +62,7 @@ object EnchantmentUtil {
enchantment2.conflictsWith(enchantment1) enchantment2.conflictsWith(enchantment1)
} }
if (hasConflict) { if (hasConflict) {
return hasConflict return true
} }
} }
return false return false

View file

@ -13,15 +13,13 @@ class EnchantConflictGroup(val cantConflict: MaterialGroup, val minBeforeBlock:
} }
fun allow(item: ItemStack) : Boolean{ fun allow(item: ItemStack) : Boolean{
if(enchantments.size > minBeforeBlock){ if(enchantments.size < minBeforeBlock){
return true return true
} }
if(cantConflict.contain(item.type)){ if(cantConflict.contain(item.type)){
return true return true
} }
if(minBeforeBlock == 0){
return false
}
// 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
@ -36,5 +34,9 @@ class EnchantConflictGroup(val cantConflict: MaterialGroup, val minBeforeBlock:
return true return true
} }
fun isEnchantEmpty(): Boolean {
return enchantments.size == 0
}
} }

View file

@ -0,0 +1,113 @@
package xyz.alexcrea.group
import io.delilaheve.UnsafeEnchants
import org.bukkit.NamespacedKey
import org.bukkit.configuration.ConfigurationSection
import org.bukkit.configuration.file.YamlConfiguration
import org.bukkit.enchantments.Enchantment
import org.bukkit.inventory.ItemStack
import kotlin.collections.ArrayList
class EnchantConflictManager {
companion object {
// Path for the enchantments list
private const val ENCH_LIST_PATH = "enchantments"
// Path for group list related to the conflict
private const val CONFLICT_GROUP_PATH = "notAffectedGroups"
// Path for the maximum number of enchantment before validating the conflict
private const val ENCH_MAX_PATH = "maxEnchantmentBeforeConflict"
// Default name for an empty Material group
private val DEFAULT_EMPTY_GROUP = IncludeGroup("empty")
// Default name for a joining group
private const val DEFAULT_GROUP_NAME = "joinedGroup"
}
private lateinit var conflictList: ArrayList<EnchantConflictGroup>
// Read and prepare all conflict
fun prepareConflicts(config: YamlConfiguration, itemManager: ItemGroupManager){
conflictList = ArrayList()
val keys = config.getKeys(false)
for (key in keys) {
val section = config.getConfigurationSection(key)!!
val conflict = createConflict(section,itemManager,key)
conflictList.add(conflict)
}
}
// create and read a conflict from a yaml section
private fun createConflict(section: ConfigurationSection,
itemManager: ItemGroupManager,
conflictName: String): EnchantConflictGroup {
// Create conflict
val conflict = createConflictObject(section,itemManager,conflictName)
// Read and add enchantment to conflict
val enchantList = section.getStringList(ENCH_LIST_PATH)
for (enchantName in enchantList) {
val enchantKey = NamespacedKey.minecraft(enchantName)
val enchant = Enchantment.getByKey(enchantKey)
if(enchant == null){
UnsafeEnchants.instance.logger.warning("Enchantment $enchantName do not exist but was asked for conflict $conflictName")
continue
}
conflict.addEnchantment(enchant)
}
if(conflict.isEnchantEmpty()){
UnsafeEnchants.instance.logger.warning("Conflict $conflictName do not have valid enchantment, it will not work")
}
return conflict
}
private fun createConflictObject(section: ConfigurationSection,
itemManager: ItemGroupManager,
conflictName: String): EnchantConflictGroup {
// Get the maximum number of enchantment before validating the conflict
var minBeforeBlock = section.getInt(ENCH_MAX_PATH,0)
if(minBeforeBlock < 0){
minBeforeBlock = 0
UnsafeEnchants.instance.logger.warning("Conflict $conflictName have an invalid value of $ENCH_MAX_PATH")
UnsafeEnchants.instance.logger.warning("It should be more or equal to 0. default to 0")
}
// Find or create the selected group for the conflict
val groupList = section.getStringList(CONFLICT_GROUP_PATH)
val finalGroup: MaterialGroup
if(groupList.size < 1){
finalGroup = DEFAULT_EMPTY_GROUP
}else if(groupList.size == 1){
finalGroup = findGroup(groupList[0], itemManager, conflictName)
}else{
finalGroup = IncludeGroup(DEFAULT_GROUP_NAME)
for (groupName in groupList) {
finalGroup.addToPolicy(findGroup(groupName, itemManager, conflictName))
}
}
// Return conflict
return EnchantConflictGroup(finalGroup, minBeforeBlock)
}
private fun findGroup(groupName: String,itemManager: ItemGroupManager, conflictName: String): MaterialGroup {
val group = itemManager.get(groupName)
if(group == null){
UnsafeEnchants.instance.logger.warning("Group $groupName do not exist but is ask by conflict $conflictName")
return DEFAULT_EMPTY_GROUP
}
return group
}
fun isConflicting(item: ItemStack): Boolean{
for (conflict in conflictList) {
if(!conflict.allow(item)) {
return true
}
}
return false
}
}

View file

@ -102,6 +102,11 @@ class ItemGroupManager {
} }
// Get the selected group or return null if it doesn't exist
fun get(groupName: String): MaterialGroup? {
return groupMap[groupName]
}
} }
enum class GroupType(private val groupID: String) { enum class GroupType(private val groupID: String) {