Add material groups and prepare additional permissions.

This commit is contained in:
alexcrea 2024-01-31 19:46:44 +01:00
parent e2aa0509f0
commit e18e5b224e
8 changed files with 256 additions and 2 deletions

View file

@ -34,6 +34,9 @@ class AnvilEventListener : Listener {
// Permission node required for the plugin to take over enchantment combination
private val requirePermission: Permission
get() = Permission(UnsafeEnchants.unsafePermission)
// Permission node to bypass illegal group check
private val bypassPermission: Permission
get() = Permission(UnsafeEnchants.unsafeBypassPermission)
/**
* Event handler logic for when an anvil contains items to be combined
@ -85,7 +88,10 @@ class AnvilEventListener : Listener {
val player = event.whoClicked as? Player ?: 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 }
event.result = Event.Result.ALLOW
}

View file

@ -1,7 +1,9 @@
package io.delilaheve
import io.delilaheve.util.ConfigOptions
import org.bukkit.configuration.file.YamlConfiguration
import org.bukkit.plugin.java.JavaPlugin
import xyz.alexcrea.group.ItemGroupManager
/**
* Bukkit/Spigot/Paper plugin to alter enchantment max
@ -12,8 +14,15 @@ class UnsafeEnchants : JavaPlugin() {
companion object {
// Permission string required to use the plugin's features
const val unsafePermission = "ue.unsafe"
// Permission string required to bypass illegal enchantment group
const val unsafeBypassPermission = "ue.unsafe_all"
// Item Grouping Configuration file name
const val itemGroupingConfigName = "item_groups.yml"
// Current plugin instance
lateinit var instance: UnsafeEnchants
// Current item grouping configuration instance
lateinit var itemGroups: ItemGroupManager
/**
* Logging handler
@ -31,6 +40,21 @@ class UnsafeEnchants : JavaPlugin() {
override fun onEnable() {
instance = this
saveDefaultConfig()
// Save default material grouping config
saveResource(itemGroupingConfigName,false)
// Load material grouping config
val itemGroupConfig = YamlConfiguration()
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
itemGroups = ItemGroupManager()
itemGroups.prepareGroups(itemGroupConfig)
server.pluginManager.registerEvents(
AnvilEventListener(),
this

View file

@ -0,0 +1,12 @@
package xyz.alexcrea.group
import org.bukkit.Material
class ExcludeGroup(name: String): IncludeGroup(name) {
override fun contain(mat: Material): Boolean {
Material.POLISHED_DIORITE
return !super.contain(mat)
}
}

View file

@ -0,0 +1,42 @@
package xyz.alexcrea.group
import org.bukkit.Material
open class IncludeGroup(private val name: String): MaterialGroup{
private val includedMaterial = HashSet<Material>()
private val includedGroup = HashSet<MaterialGroup>()
override fun contain(mat: Material): Boolean {
if(mat in includedMaterial){
return true
}
for (materialGroup in includedGroup.iterator()) {
if(materialGroup.contain(mat)){
return true
}
}
return false
}
override fun isReferencing(other: MaterialGroup): Boolean {
for (materialGroup in includedGroup.iterator()) {
if((materialGroup == other) || (materialGroup.isReferencing(other))){
return true
}
}
return false
}
override fun addToPolicy(mat: Material) {
includedMaterial.add(mat)
}
override fun addToPolicy(other: MaterialGroup) {
includedGroup.add(other)
}
override fun getName(): String {
return name
}
}

View file

@ -0,0 +1,118 @@
package xyz.alexcrea.group
import io.delilaheve.UnsafeEnchants
import org.bukkit.Material
import org.bukkit.configuration.ConfigurationSection
import org.bukkit.configuration.file.YamlConfiguration
import java.util.*
import kotlin.collections.HashMap
class ItemGroupManager {
companion object {
// Path for group type
private const val GROUP_TYPE_PATH = "type"
private const val MATERIAL_LIST_PATH = "items"
private const val GROUP_LIST_PATH = "groups"
}
private lateinit var groupMap : HashMap<String,MaterialGroup>
// Read and create material groups
fun prepareGroups(config: YamlConfiguration){
groupMap = HashMap()
val keys = config.getKeys(false)
for (key in keys) {
if(groupMap.containsKey(key))
continue
createGroup(config, keys, key)
}
}
// Create group by key
private fun createGroup(config: YamlConfiguration,
keys: Set<String>,
key: String): MaterialGroup{
val groupSection = config.getConfigurationSection(key)!!
val groupType = groupSection.getString(GROUP_TYPE_PATH,null)
// Create Material group according to the group type
val group: MaterialGroup
if(GroupType.EXCLUDE.equal(groupType)){
group = ExcludeGroup(key)
}else {
group = IncludeGroup(key)
if(!GroupType.INCLUDE.equal(groupType)){
UnsafeEnchants.instance.logger.warning("Group $key have an invalid group type. default to Include.")
}
}
groupMap[key] = group
readGroup(group, groupSection, config, keys)
return group
}
// Read Group elements
private fun readGroup(group: MaterialGroup,
groupSection: ConfigurationSection,
config: YamlConfiguration,
keys: Set<String>){
// Read material to include in this group policy
val materialList = groupSection.getStringList(MATERIAL_LIST_PATH)
for (materialTemp in materialList) {
val materialName = materialTemp.uppercase(Locale.getDefault())
val material = Material.getMaterial(materialName)
if(material == null){
UnsafeEnchants.instance.logger.warning(
"Unknown material $materialTemp on group ${group.getName()}")
continue
}
group.addToPolicy(material)
}
// Read group to include in this group policy.
// please note the group name is case-sensitive.
val groupList = groupSection.getStringList(GROUP_LIST_PATH)
for (groupName in groupList) {
if(groupName !in keys){
UnsafeEnchants.instance.logger.warning(
"Group $groupName do not exist but is included in group ${group.getName()}")
continue
}
// Get other group or create it if not yet created
val otherGroup = if(!groupMap.containsKey(groupName)){
createGroup(config,keys,groupName)
}else{
groupMap[groupName]!!
}
// Avoid self reference or it will create an infinite loop
if(otherGroup.isReferencing(group)){
UnsafeEnchants.instance.logger.warning(
"Group $groupName is on a reference loop with group ${group.getName()} !")
UnsafeEnchants.instance.logger.warning(
"Please fix it in your item_groups config or the plugin will probably not work as expected.")
continue
}
group.addToPolicy(otherGroup)
}
}
}
enum class GroupType(private val groupID: String) {
INCLUDE("include"),
EXCLUDE("exclude")
;
// Test if string is equal to the groupID of this enum
fun equal(toTest: String?): Boolean{
if(toTest == null)
return false
return groupID.contentEquals(toTest.lowercase(Locale.getDefault()))
}
}

View file

@ -0,0 +1,22 @@
package xyz.alexcrea.group
import org.bukkit.Material
interface MaterialGroup {
// Get if a material is allowed following the group policy
fun contain(mat : Material): Boolean
// Get if a group is referenced by this
fun isReferencing(other : MaterialGroup): Boolean
// Push a material to this group to follow this group policy
fun addToPolicy(mat : Material)
// Push a group to this group to follow this group policy
fun addToPolicy(other : MaterialGroup)
// Get the group name in case something is wrong
fun getName(): String
}

View file

@ -0,0 +1,27 @@
# Please note this config use spigot material names.
# It should match minecraft name in most case, maybe every case, but I can't be sure
# In case there an issue with material name, you can found them here:
# https://hub.spigotmc.org/javadocs/spigot/org/bukkit/Material.html
# An empty Exclude group exclude nothing, so it contain everything
everything:
type: exclude
# An empty include group will include nothing
nothing:
type: include
# This group is an example of a group including only stone and polished granite
example_include:
type: include
items:
- stone
- polished_granite
# This group contain everything except polished granite and elements of example_include
example_exclude:
type: exclude
items:
- polished_granite
groups:
- example_include

View file

@ -8,4 +8,7 @@ author: DelilahEve
permissions:
ue.unsafe:
default: true
description: Allow player to combine "unsafe" enchants
description: Allow player to combine allowed "unsafe" enchants
ue.unsafe_all:
default: false
description: Allow player to combine every "unsafe" enchants