renamed the plugin

This commit is contained in:
alexcrea 2024-02-14 01:28:48 +01:00
parent 944e4b025c
commit c366b45e16
12 changed files with 125 additions and 100 deletions

View file

@ -1,40 +1,48 @@
# UnsafeEnchants+
# Custom Anvil
**UnsafeEnchants+** is a fully configurable plugin for bukkit, spigot, and paper minecraft servers
allowing custom enchantment limits and customising combination restrictions.
**Custom Anvil** is a plugin to allow admin to customise evey aspect of the anvil's mechanics.
It is expected to work on 1.18 to 1.20.4 minecraft servers running spigot or paper.
**UnsafeEnchants+** is based on [UnsafeEnchants](https://github.com/DelilahEve/UnsafeEnchants). You can find it on
**Custom Anvil** was previously named **Unsafe Enchants+**.
It was renamed because it now affects every anvil aspect and not only unsafe enchants
**Custom Anvil** is based on [Unsafe Enchants](https://github.com/DelilahEve/UnsafeEnchants) by DelilahEve. You can find it on
[GitHub](https://github.com/DelilahEve/UnsafeEnchants/releases/latest),
[Spigot](https://www.spigotmc.org/resources/unsafe-enchants.104708/) or
[CurseForge](https://www.curseforge.com/minecraft/bukkit-plugins/unsafe-enchants/files/all)
**UnsafeEnchants+** add the following to [UnsafeEnchants](https://github.com/DelilahEve/UnsafeEnchants):
- Make default configuration more vanilla like
- Fix a xp bug with enchanted book
- Custom enchantment restriction configuration
---
### Know issue:
There is non known issue, if you find one please report the issue.
---
### Download Locations:
the plugin can be downloaded on the
[Spigot site](https://www.spigotmc.org/resources/unsafe-enchants.114884/)
the plugin can be downloaded on the
[Spigot site](https://www.spigotmc.org/resources/unsafe-enchants.114884/)
or [on GitHub](https://github.com/alexcrea/UnsafeEnchantsPlus/releases/latest)
---
**Custom Anvil** have the following features:
- Vanilla like default configuration
- Custom enchantment level limit
- Custom enchant restrictions (allow unsafe enchantment only for a group of item or create new restriction)
- Custom items of unit repairs (repair damaged with unit of "material", for example the repair of diamond sword by diamonds)
- Custom XP cost for every aspect of the anvil
- Permissions to bypass level limit or enchantment restriction.
---
### Permissions:
```yml
ue.unsafe: Allows use of custom restriction rules
ue.bypass.fuse: Bypass every enchantment restriction check. Including custom restrictions
ue.bypass.level: Bypass max level check. Including custom max level
ca.affected: Player with this permission will be affected by the plugin
ca.bypass.fuse: Allow player to combine every enchantments to every item (no custom limit)
ca.bypass.level: Allow player to bypass every level limit (no custom limit)
ca.command.reload: Allow administrator to reload the plugin's configs
```
### Commands
```yml
anvilconfigreload or carl: Reload every config of this plugin
```
---
### Default Configuration:
Default configuration can be found on following links:
- [config.yml](https://github.com/alexcrea/UnsafeEnchantsPlus/blob/master/src/main/resources/config.yml)
- [enchant_conflict.yml](https://github.com/alexcrea/UnsafeEnchantsPlus/blob/master/src/main/resources/enchant_conflict.yml)
- [item_groups.yml](https://github.com/alexcrea/UnsafeEnchantsPlus/blob/master/src/main/resources/item_groups.yml)
- [unit_repair_item.yml](https://github.com/alexcrea/UnsafeEnchantsPlus/blob/master/src/main/resources/unit_repair_item.yml)
---
### Know issue:
There is non known issue, if you find one please report the issue.

View file

@ -54,7 +54,7 @@ class AnvilEventListener : Listener {
// Should find player
val player = event.view.player
if(!player.hasPermission(UnsafeEnchants.unsafePermission)) return
if(!player.hasPermission(CustomAnvil.unsafePermission)) return
// Test rename lonely item
if(second == null){
@ -150,7 +150,7 @@ class AnvilEventListener : Listener {
@EventHandler(ignoreCancelled = true)
fun anvilExtractionCheck(event: InventoryClickEvent) {
val player = event.whoClicked as? Player ?: return
if(!player.hasPermission(UnsafeEnchants.unsafePermission)) return
if(!player.hasPermission(CustomAnvil.unsafePermission)) return
val inventory = event.inventory as? AnvilInventory ?: return
if (event.rawSlot != ANVIL_OUTPUT_SLOT) { return }
val output = inventory.getItem(ANVIL_OUTPUT_SLOT) ?: return
@ -291,7 +291,7 @@ class AnvilEventListener : Listener {
result.itemMeta = it
}
UnsafeEnchants.log("Calculated penalty: " +
CustomAnvil.log("Calculated penalty: " +
"leftPenalty: $leftPenalty, " +
"rightPenalty: $rightPenalty, " +
"result penalty: ${(result.itemMeta as? Repairable)?.repairCost ?: "none"}")
@ -316,7 +316,7 @@ class AnvilEventListener : Listener {
// count enchant as illegal enchant if it conflicts with another enchant or not in result
if((enchantment.key !in resultEnchsKeys)){
resultEnchsKeys.add(enchantment.key)
val conflictType = UnsafeEnchants.conflictManager.isConflicting(resultEnchsKeys,result.type,enchantment.key)
val conflictType = CustomAnvil.conflictManager.isConflicting(resultEnchsKeys,result.type,enchantment.key)
resultEnchsKeys.remove(enchantment.key)
if(ConflictType.BIG_CONFLICT == conflictType){
@ -329,11 +329,11 @@ class AnvilEventListener : Listener {
val enchantmentMultiplier = ConfigOptions.enchantmentValue(enchantment.key, rightIsFormBook)
val value = resultLevel * enchantmentMultiplier
UnsafeEnchants.log("Value for ${enchantment.key.enchantmentName} level ${enchantment.value} is $value")
CustomAnvil.log("Value for ${enchantment.key.enchantmentName} level ${enchantment.value} is $value")
rightValue += value
}
UnsafeEnchants.log("Calculated right values: " +
CustomAnvil.log("Calculated right values: " +
"rightValue: $rightValue, " +
"illegalPenalty: $illegalPenalty")
@ -351,10 +351,10 @@ class AnvilEventListener : Listener {
/* 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. */
UnsafeEnchants.instance
CustomAnvil.instance
.server
.scheduler
.runTask(UnsafeEnchants.instance, Runnable {
.runTask(CustomAnvil.instance, Runnable {
if (ConfigOptions.removeRepairLimit) {
inventory.maximumRepairCost = Int.MAX_VALUE
}

View file

@ -16,23 +16,23 @@ import java.io.FileReader
* Bukkit/Spigot/Paper plugin to alter enchantment max
* levels and allow unsafe enchantment combinations
*/
class UnsafeEnchants : JavaPlugin() {
class CustomAnvil : JavaPlugin() {
companion object {
// bstats plugin id
private const val bstatsPluginId = 20923
// Permission string required to use the plugin's features
const val unsafePermission = "ue.unsafe"
const val unsafePermission = "ca.unsafe"
// Permission string required to bypass enchantment conflicts test
const val bypassFusePermission = "ue.bypass.fuse"
const val bypassFusePermission = "ca.bypass.fuse"
// Permission string required to bypass enchantment conflicts test
const val bypassLevelPermission = "ue.bypass.level"
const val bypassLevelPermission = "ca.bypass.level"
// Permission string required to reload the config
const val commandReloadPermission = "ue.command.reload"
const val commandReloadPermission = "ca.command.reload"
// Command Name to reload the config
const val commandReloadName = "reloadunsafeenchants"
const val commandReloadName = "anvilconfigreload"
// Item Grouping Configuration file name
const val itemGroupingConfigFilePath = "item_groups.yml"
@ -42,7 +42,7 @@ class UnsafeEnchants : JavaPlugin() {
const val unitRepairFilePath = "unit_repair_item.yml"
// Current plugin instance
lateinit var instance: UnsafeEnchants
lateinit var instance: CustomAnvil
// Current item grouping configuration instance
lateinit var conflictManager: EnchantConflictManager
@ -65,6 +65,14 @@ class UnsafeEnchants : JavaPlugin() {
override fun onEnable() {
instance = this
// Disable old plugin name if exist
val potentialPlugin = Bukkit.getPluginManager().getPlugin("UnsafeEnchantsPlus")
if(potentialPlugin != null){
Bukkit.getPluginManager().disablePlugin(potentialPlugin)
logger.warning("An old version of this plugin was detected")
logger.warning("Please note CustomAnvil is a more recent version of UnsafeEnchantsPlus")
}
reloadAllConfigs()
// Load metrics
val metric = Metrics(this, bstatsPluginId)
@ -78,7 +86,6 @@ class UnsafeEnchants : JavaPlugin() {
AnvilEventListener(),
this
)
}
fun reloadAllConfigs(){
@ -100,8 +107,8 @@ class UnsafeEnchants : JavaPlugin() {
val unitRepairConfig = reloadResource(unitRepairFilePath) ?: return
// Set the global variable
UnsafeEnchants.conflictManager = conflictManager
UnsafeEnchants.unitRepairConfig = unitRepairConfig
CustomAnvil.conflictManager = conflictManager
CustomAnvil.unitRepairConfig = unitRepairConfig
// Test if default config
MetricsUtil.testIfConfigIsDefault(config, itemGroupConfig, conflictConfig, unitRepairConfig)

View file

@ -1,6 +1,6 @@
package io.delilaheve.util
import io.delilaheve.UnsafeEnchants
import io.delilaheve.CustomAnvil
import io.delilaheve.util.EnchantmentUtil.enchantmentName
import org.bukkit.enchantments.Enchantment
@ -71,7 +71,7 @@ object ConfigOptions {
*/
private val defaultEnchantLimit: Int
get() {
return UnsafeEnchants.instance
return CustomAnvil.instance
.config
.getInt(DEFAULT_LIMIT_PATH, DEFAULT_ENCHANT_LIMIT)
}
@ -81,7 +81,7 @@ object ConfigOptions {
*/
val limitRepairCost: Boolean
get() {
return UnsafeEnchants.instance
return CustomAnvil.instance
.config
.getBoolean(LIMIT_REPAIR_COST, DEFAULT_LIMIT_REPAIR)
}
@ -91,7 +91,7 @@ object ConfigOptions {
*/
val limitRepairValue: Int
get() {
return UnsafeEnchants.instance
return CustomAnvil.instance
.config
.getInt(LIMIT_REPAIR_VALUE, DEFAULT_LIMIT_REPAIR_VALUE)
.takeIf { it in REPAIR_LIMIT_RANGE }
@ -103,7 +103,7 @@ object ConfigOptions {
*/
val itemRepairCost: Int
get() {
return UnsafeEnchants.instance
return CustomAnvil.instance
.config
.getInt(ITEM_REPAIR_COST, DEFAULT_ITEM_REPAIR_COST)
.takeIf { it in REPAIR_COST_RANGE }
@ -115,7 +115,7 @@ object ConfigOptions {
*/
val unitRepairCost: Int
get() {
return UnsafeEnchants.instance
return CustomAnvil.instance
.config
.getInt(UNIT_REPAIR_COST, DEFAULT_UNIT_REPAIR_COST)
.takeIf { it in REPAIR_COST_RANGE }
@ -127,7 +127,7 @@ object ConfigOptions {
*/
val itemRenameCost: Int
get() {
return UnsafeEnchants.instance
return CustomAnvil.instance
.config
.getInt(ITEM_RENAME_COST, DEFAULT_ITEM_RENAME_COST)
.takeIf { it in ITEM_RENAME_COST_RANGE }
@ -139,7 +139,7 @@ object ConfigOptions {
*/
val sacrificeIllegalCost: Int
get() {
return UnsafeEnchants.instance
return CustomAnvil.instance
.config
.getInt(SACRIFICE_ILLEGAL_COST, DEFAULT_SACRIFICE_ILLEGAL_COST)
.takeIf { it in SACRIFICE_ILLEGAL_COST_RANGE }
@ -150,7 +150,7 @@ object ConfigOptions {
*/
val removeRepairLimit: Boolean
get() {
return UnsafeEnchants.instance
return CustomAnvil.instance
.config
.getBoolean(REMOVE_REPAIR_LIMIT, DEFAULT_REMOVE_LIMIT)
}
@ -160,7 +160,7 @@ object ConfigOptions {
*/
val debugLog: Boolean
get() {
return UnsafeEnchants.instance
return CustomAnvil.instance
.config
.getBoolean(DEBUG_LOGGING, DEFAULT_DEBUG_LOG)
}
@ -170,7 +170,7 @@ object ConfigOptions {
*/
fun enchantLimit(enchantment: Enchantment): Int {
val path = "${ENCHANT_LIMIT_ROOT}.${enchantment.enchantmentName}"
return UnsafeEnchants.instance
return CustomAnvil.instance
.config
.getInt(path, defaultEnchantLimit)
.takeIf { it in ENCHANT_LIMIT_RANGE }
@ -187,7 +187,7 @@ object ConfigOptions {
): Int {
val typeKey = if (isFromBook) KEY_BOOK else KEY_ITEM
val path = "${ENCHANT_VALUES_ROOT}.${enchantment.enchantmentName}.$typeKey"
return UnsafeEnchants.instance
return CustomAnvil.instance
.config
.getInt(path, DEFAULT_ENCHANT_VALUE)
.takeIf { it >= DEFAULT_ENCHANT_VALUE }

View file

@ -1,6 +1,6 @@
package io.delilaheve.util
import io.delilaheve.UnsafeEnchants
import io.delilaheve.CustomAnvil
import org.bukkit.Material
import org.bukkit.enchantments.Enchantment
import org.bukkit.entity.HumanEntity
@ -33,8 +33,8 @@ object EnchantmentUtil {
if (!containsKey(enchantment)) {
// 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) != ConflictType.NO_CONFLICT)){
if(!player.hasPermission(CustomAnvil.bypassFusePermission) &&
(CustomAnvil.conflictManager.isConflicting(this.keys,mat,enchantment) != ConflictType.NO_CONFLICT)){
this.remove(enchantment)
}
@ -42,8 +42,8 @@ object EnchantmentUtil {
// Enchantment already in result list
else{
// ... and they are conflicting
if((UnsafeEnchants.conflictManager.isConflicting(this.keys,mat,enchantment) != ConflictType.NO_CONFLICT)
&& !player.hasPermission(UnsafeEnchants.bypassFusePermission)){
if((CustomAnvil.conflictManager.isConflicting(this.keys,mat,enchantment) != ConflictType.NO_CONFLICT)
&& !player.hasPermission(CustomAnvil.bypassFusePermission)){
return@forEach
}
@ -58,7 +58,7 @@ object EnchantmentUtil {
// try to increase the enchantment level by 1
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(CustomAnvil.bypassLevelPermission)){
255
}else{
ConfigOptions.enchantLimit(enchantment)

View file

@ -1,6 +1,6 @@
package io.delilaheve.util
import io.delilaheve.UnsafeEnchants
import io.delilaheve.CustomAnvil
import org.bukkit.Material.ENCHANTED_BOOK
import org.bukkit.enchantments.Enchantment
import org.bukkit.inventory.ItemStack
@ -59,7 +59,7 @@ object ItemUtil {
}
enchantments.forEach { (enchant, level) ->
val added = addStoredEnchant(enchant, level, true)
UnsafeEnchants.log("${enchant.key} added to item? $added")
CustomAnvil.log("${enchant.key} added to item? $added")
}
}

View file

@ -1,13 +1,13 @@
package xyz.alexcrea.command
import io.delilaheve.UnsafeEnchants
import io.delilaheve.CustomAnvil
import org.bukkit.command.Command
import org.bukkit.command.CommandExecutor
import org.bukkit.command.CommandSender
class ReloadExecutor : CommandExecutor {
override fun onCommand(sender: CommandSender, cmd: Command, cmdstr: String, args: Array<out String>): Boolean {
if(!sender.hasPermission(UnsafeEnchants.commandReloadPermission)) {
if(!sender.hasPermission(CustomAnvil.commandReloadPermission)) {
sender.sendMessage("§cYou do not have permission to reload the config")
return false
}
@ -26,9 +26,10 @@ class ReloadExecutor : CommandExecutor {
*/
private fun commandBody(): Boolean{
try {
UnsafeEnchants.instance.reloadAllConfigs()
CustomAnvil.instance.reloadAllConfigs()
return true
}catch (ignored: Exception){
}catch (e: Exception){
e.printStackTrace()
return false
}
}

View file

@ -1,6 +1,6 @@
package xyz.alexcrea.group
import io.delilaheve.UnsafeEnchants
import io.delilaheve.CustomAnvil
import org.bukkit.Material
import org.bukkit.NamespacedKey
import org.bukkit.configuration.ConfigurationSection
@ -69,7 +69,7 @@ class EnchantConflictManager {
val enchant = Enchantment.getByKey(enchantKey)
if(enchant == null){
if(!futureUse){
UnsafeEnchants.instance.logger.warning("Enchantment $enchantName do not exist but was asked for conflict $conflictName")
CustomAnvil.instance.logger.warning("Enchantment $enchantName do not exist but was asked for conflict $conflictName")
}
continue
}
@ -77,7 +77,7 @@ class EnchantConflictManager {
}
if(conflict.getEnchants().size == 0){
if(!futureUse){
UnsafeEnchants.instance.logger.warning("Conflict $conflictName do not have valid enchantment, it will not work")
CustomAnvil.instance.logger.warning("Conflict $conflictName do not have valid enchantment, it will not work")
}
return null
}
@ -92,8 +92,8 @@ class EnchantConflictManager {
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")
CustomAnvil.instance.logger.warning("Conflict $conflictName have an invalid value of $ENCH_MAX_PATH")
CustomAnvil.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)
@ -115,7 +115,7 @@ class EnchantConflictManager {
private fun findGroup(groupName: String,itemManager: ItemGroupManager, conflictName: String): AbstractMaterialGroup {
val group = itemManager.get(groupName)
if(group == null){
UnsafeEnchants.instance.logger.warning("Group $groupName do not exist but is ask by conflict $conflictName")
CustomAnvil.instance.logger.warning("Group $groupName do not exist but is ask by conflict $conflictName")
return DEFAULT_EMPTY_GROUP
}

View file

@ -1,6 +1,6 @@
package xyz.alexcrea.group
import io.delilaheve.UnsafeEnchants
import io.delilaheve.CustomAnvil
import org.bukkit.Material
import org.bukkit.configuration.ConfigurationSection
import org.bukkit.configuration.file.YamlConfiguration
@ -48,7 +48,7 @@ class ItemGroupManager {
}else {
group = IncludeGroup(key)
if(!GroupType.INCLUDE.equal(groupType)){
UnsafeEnchants.instance.logger.warning("Group $key have an invalid group type. default to Include.")
CustomAnvil.instance.logger.warning("Group $key have an invalid group type. default to Include.")
}
}
@ -70,7 +70,7 @@ class ItemGroupManager {
if(material == null){
// Check if we should warn the user
if(materialName !in FUTURE_MATERIAL){
UnsafeEnchants.instance.logger.warning(
CustomAnvil.instance.logger.warning(
"Unknown material $materialTemp on group ${group.getName()}")
}
@ -84,7 +84,7 @@ class ItemGroupManager {
val groupList = groupSection.getStringList(GROUP_LIST_PATH)
for (groupName in groupList) {
if(groupName !in keys){
UnsafeEnchants.instance.logger.warning(
CustomAnvil.instance.logger.warning(
"Group $groupName do not exist but is included in group ${group.getName()}")
continue
}
@ -96,9 +96,9 @@ class ItemGroupManager {
}
// Avoid self reference or it will create an infinite loop
if(otherGroup.isReferencing(group)){
UnsafeEnchants.instance.logger.warning(
CustomAnvil.instance.logger.warning(
"Group $groupName is on a reference loop with group ${group.getName()} !")
UnsafeEnchants.instance.logger.warning(
CustomAnvil.instance.logger.warning(
"Please fix it in your item_groups config or the plugin will probably not work as expected.")
continue
}

View file

@ -1,6 +1,6 @@
package xyz.alexcrea.util
import io.delilaheve.UnsafeEnchants
import io.delilaheve.CustomAnvil
import io.delilaheve.util.ConfigOptions
import org.bukkit.configuration.ConfigurationSection
@ -85,12 +85,12 @@ object MetricsUtil {
isDefaultUnitRepairItemConfig = unitRepairItemConfigHash == unitRepairConfig
// If not default and debug flag active, print the hash.
if(ConfigOptions.debugLog){
if(!isDefaultBaseConfig){UnsafeEnchants.log("baseConfig: $baseConfig")}
if(!isDefaultEnchantLimitsConfig){UnsafeEnchants.log("limitEnchantConfig: $limitEnchantConfig")}
if(!isDefaultEnchantValuesConfig){UnsafeEnchants.log("enchantValueConfig: $enchantValueConfig")}
if(!isDefaultEnchantConflictConfig){UnsafeEnchants.log("enchantConflictConfig: $enchantConflictConfig")}
if(!isDefaultItemGroupsConfig){UnsafeEnchants.log("itemGroupConfig: $itemGroupConfig")}
if(!isDefaultUnitRepairItemConfig){UnsafeEnchants.log("unitRepairConfig: $unitRepairConfig")}
if(!isDefaultBaseConfig){CustomAnvil.log("baseConfig: $baseConfig")}
if(!isDefaultEnchantLimitsConfig){CustomAnvil.log("limitEnchantConfig: $limitEnchantConfig")}
if(!isDefaultEnchantValuesConfig){CustomAnvil.log("enchantValueConfig: $enchantValueConfig")}
if(!isDefaultEnchantConflictConfig){CustomAnvil.log("enchantConflictConfig: $enchantConflictConfig")}
if(!isDefaultItemGroupsConfig){CustomAnvil.log("itemGroupConfig: $itemGroupConfig")}
if(!isDefaultUnitRepairItemConfig){CustomAnvil.log("unitRepairConfig: $unitRepairConfig")}
}
}

View file

@ -1,6 +1,6 @@
package xyz.alexcrea.util
import io.delilaheve.UnsafeEnchants
import io.delilaheve.CustomAnvil
import org.bukkit.configuration.ConfigurationSection
import org.bukkit.inventory.ItemStack
@ -19,7 +19,7 @@ object UnitRepairUtil {
other: ItemStack?
): Double? {
if(other == null) return null
val config = UnsafeEnchants.unitRepairConfig
val config = CustomAnvil.unitRepairConfig
// Get configuration section if exist
val otherName = other.type.name.uppercase()
var section = config.getConfigurationSection(otherName)

View file

@ -1,27 +1,36 @@
main: io.delilaheve.UnsafeEnchants
name: UnsafeEnchantsPlus
prefix: UnsafeEnchants+
main: io.delilaheve.CustomAnvil
name: CustomAnvil
prefix: "Custom Anvil"
version: 1.2.0
description: Allow custom illegal enchantment
description: Allow to customise anvil mechanics
api-version: 1.18
load: POSTWORLD
authors: [DelilahEve, alexcrea]
libraries:
- org.jetbrains.kotlin:kotlin-stdlib:1.6.21
commands:
reloadunsafeenchants:
anvilconfigreload:
description: Reload every config of this plugin
permission: ue.command.reload
permission: ca.command.reload
aliases:
#- acreload # anvil config reload
#- careload # custom anvil reload
- carl # custom anvil reload
permissions:
ue.unsafe:
ca.affected:
default: true
description: Allow player to combine allowed "unsafe" enchants
ue.bypass.fuse:
description: Player with this permission will be affected by the plugin
ca.bypass.fuse:
default: false
description: Allow player to combine every "unsafe" enchants
ue.bypass.level:
description: Allow player to combine every enchantments to every item (no custom limit)
ca.bypass.level:
default: false
description: Allow player to bypass max level limit
ue.command.reload:
description: Allow player to bypass every level limit (no custom limit)
ca.command.reload:
default: op
description: Allow administrator to reload the plugin's config
description: Allow administrator to reload the plugin's configs
# soft depend on old name so I can disable it if it is on the same server
# as it is the old name for this plugin
softdepend:
- UnsafeEnchantsPlus