Add Color support (#19)

Add logic to support color code (like &a) and hexadecimal color (like
#00ff00).
Create its configuration and its config GUI buttons.
This commit is contained in:
alexcrea 2024-07-28 18:46:33 +02:00 committed by GitHub
commit ab1add8fd6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 342 additions and 62 deletions

View file

@ -26,6 +26,7 @@ or [on GitHub](https://github.com/alexcrea/CustomAnvil/releases/latest)
- Display xp cost instead of "to expensive" when above lv 40. (need ProtocoLib)
- Can handle some custom enchantment plugins (see bellow for more information)
- Gui to configure the plugin in game.
- Support of color code and hexadecimal color
---
### Permissions:
```yml
@ -34,6 +35,9 @@ ca.bypass.fuse: Allow player to combine every enchantments to every item (no cus
ca.bypass.level: Allow player to bypass every level limit (no custom limit)
ca.command.reload: Allow administrator to reload the plugin's configs
ca.config.edit: Allow administrator to edit the plugin's config in game
# Related to use of color (usage of permission for color is toggleable in basic config gui or config.yml)
ca.color.code: Allow player to use color code if permission is required (toggleable)
ca.color.hex: Allow player to use hexadecimal color if permission is required (toggleable)
```
/!\ version under 1.3.1 use other permission. from 1.2.0 to 1.3.1-A1 use ua.unsafe instead of ca.affected
under 1.2.0 replace ca prefix by ue and use ue.unsafe. some permission/features may not exist before the last version.

View file

@ -13,7 +13,7 @@ plugins {
}
group = "xyz.alexcrea"
version = "1.5.3"
version = "1.5.4-beta.1"
java {
disableAutoTargetJvm()

View file

@ -59,8 +59,8 @@ public class BasicConfigGui extends ChestGui implements ValueUpdatableGui {
private void init() {
Pattern pattern = new Pattern(
GuiSharedConstant.EMPTY_GUI_FULL_LINE,
"0L0T0I0S0",
"0C0R0U0r0",
"LT0I0S0cp",
"CR0U0r0hP",
"B00000000"
);
pane = new PatternPane(0, 0, 9, 4, pattern);
@ -73,9 +73,9 @@ public class BasicConfigGui extends ChestGui implements ValueUpdatableGui {
updateGuiValues();
}
private BoolSettingsGui.BoolSettingFactory capAnvilCostFactory; // L character
private BoolSettingsGui.BoolSettingFactory capAnvilCost; // L character
private GuiItem noCapRepairItem;
private IntSettingsGui.IntSettingFactory maxAnvilCostFactory; // C character
private IntSettingsGui.IntSettingFactory maxAnvilCost; // C character
private GuiItem noMaxCostItem;
private BoolSettingsGui.BoolSettingFactory removeAnvilCostLimit; // R character
@ -86,12 +86,20 @@ public class BasicConfigGui extends ChestGui implements ValueUpdatableGui {
private IntSettingsGui.IntSettingFactory itemRenameCost; // r character
private IntSettingsGui.IntSettingFactory sacrificeIllegalEnchantCost; // S character
private BoolSettingsGui.BoolSettingFactory allowColorCode; // c character
private BoolSettingsGui.BoolSettingFactory allowHexColor; // h character
private BoolSettingsGui.BoolSettingFactory permissionNeededForColor; // p character
private GuiItem noPermissionNeededItem;
private IntSettingsGui.IntSettingFactory useOfColorCost; // P character
private GuiItem noColorCostItem;
/**
* Prepare basic gui displayed items factory and static items..
*/
protected void prepareValues() {
// cap anvil cost
this.capAnvilCostFactory = BoolSettingsGui.boolFactory("\u00A78Cap Anvil Cost ?", this,
this.capAnvilCost = BoolSettingsGui.boolFactory("\u00A78Cap Anvil Cost ?", this,
ConfigHolder.DEFAULT_CONFIG,
ConfigOptions.CAP_ANVIL_COST, ConfigOptions.DEFAULT_CAP_ANVIL_COST,
"\u00A77All anvil cost will be capped to \u00A7aMax Anvil Cost\u00A77 if enabled.",
@ -110,7 +118,7 @@ public class BasicConfigGui extends ChestGui implements ValueUpdatableGui {
// repair cost item
IntRange range = ConfigOptions.MAX_ANVIL_COST_RANGE;
this.maxAnvilCostFactory = IntSettingsGui.intFactory("\u00A78Max Anvil Cost", this,
this.maxAnvilCost = IntSettingsGui.intFactory("\u00A78Max Anvil Cost", this,
ConfigOptions.MAX_ANVIL_COST, ConfigHolder.DEFAULT_CONFIG,
Arrays.asList(
"\u00A77Max cost the Anvil can get to.",
@ -147,6 +155,10 @@ public class BasicConfigGui extends ChestGui implements ValueUpdatableGui {
ConfigOptions.REPLACE_TOO_EXPENSIVE, ConfigOptions.DEFAULT_REPLACE_TOO_EXPENSIVE,
getReplaceToExpensiveLore());
// ------------
// Cost config
// ------------
// item repair cost
range = ConfigOptions.REPAIR_COST_RANGE;
this.itemRepairCost = IntSettingsGui.intFactory("\u00A78Item Repair Cost", this,
@ -194,6 +206,70 @@ public class BasicConfigGui extends ChestGui implements ValueUpdatableGui {
ConfigOptions.DEFAULT_SACRIFICE_ILLEGAL_COST,
1, 5, 10, 50, 100);
// -------------
// Color config
// -------------
// Allow us of color code
this.allowColorCode = BoolSettingsGui.boolFactory("\u00A78Allow Use Of Color Code ?", this,
ConfigHolder.DEFAULT_CONFIG,
ConfigOptions.ALLOW_COLOR_CODE, ConfigOptions.DEFAULT_ALLOW_COLOR_CODE,
"\u00A77Whether players can use color code.",
"\u00A77Color code a formatted like \u00A7a&a\u00A77 and is used in the rename field of the anvil.",
"\u00A77Player may need permission to use color code if \u00A7ePlayer need permission to use color\u00A77 is enabled.");
// Allow us of hexadecimal color
this.allowHexColor = BoolSettingsGui.boolFactory("\u00A78Allow Use Of Hexadecimal Color ?", this,
ConfigHolder.DEFAULT_CONFIG,
ConfigOptions.ALLOW_HEXADECIMAL_COLOR, ConfigOptions.DEFAULT_ALLOW_HEXADECIMAL_COLOR,
"\u00A77Whether players can use hexadecimal color.",
"\u00A77Color code a formatted like \u00A72#012345 \u00A77and is used in the rename field of the anvil.",
"\u00A77Player may need permission to use color code if \u00A7ePermission Needed For Color\u00A77 is enabled.");
// Permission needed for color
this.permissionNeededForColor = BoolSettingsGui.boolFactory("\u00A78Need Permission To Use Color ?", this,
ConfigHolder.DEFAULT_CONFIG,
ConfigOptions.PERMISSION_NEEDED_FOR_COLOR, ConfigOptions.DEFAULT_PERMISSION_NEEDED_FOR_COLOR,
"\u00A77Whether players should have permission to be able to use colors.",
"\u00A77Give player \u00A7eca.color.code\u00A77 Permission to allow use of color code.",
"\u00A77Give player \u00A7eca.color.hex\u00A77 Permission to allow use of hexadecimal color.");
// Permission needed for color not necessary
item = new ItemStack(Material.BARRIER);
meta = item.getItemMeta();
assert meta != null;
meta.setDisplayName("\u00A7cNeed Permission To Use Color ?");
meta.setLore(Arrays.asList("\u00A77This config can do something only if one of the following config is enabled:",
"\u00A77- \u00A7aAllow Use Of Color Code",
"\u00A77- \u00A7aAllow Use Of Hexadecimal Color"));
item.setItemMeta(meta);
this.noPermissionNeededItem = new GuiItem(item, GuiGlobalActions.stayInPlace, CustomAnvil.instance);
// Cost of using color
range = ConfigOptions.USE_OF_COLOR_COST_RANGE;
this.useOfColorCost = IntSettingsGui.intFactory("\u00A78Cost Of Using Color", this,
ConfigOptions.USE_OF_COLOR_COST, ConfigHolder.DEFAULT_CONFIG,
Arrays.asList(
"\u00A77XP level cost when using color code or hexadecimal color using the anvil.",
"\u00A77conflict With one of the left item enchantment"
),
range.getFirst(), range.getLast(),
ConfigOptions.DEFAULT_USE_OF_COLOR_COST,
1, 5, 10, 50, 100);
// Permission needed for color not necessary
item = new ItemStack(Material.BARRIER);
meta = item.getItemMeta();
assert meta != null;
meta.setDisplayName("\u00A7cCost Of Using Color");
meta.setLore(Arrays.asList("\u00A77This config can do something only if one of the following config is enabled:",
"\u00A77- \u00A7aAllow Use Of Color Code",
"\u00A77- \u00A7aAllow Use Of Hexadecimal Color"));
item.setItemMeta(meta);
this.noColorCostItem = new GuiItem(item, GuiGlobalActions.stayInPlace, CustomAnvil.instance);
}
@NotNull
@ -219,8 +295,8 @@ public class BasicConfigGui extends ChestGui implements ValueUpdatableGui {
GuiItem capAnvilCostItem;
GuiItem maxAnvilCostItem;
if (!this.removeAnvilCostLimit.getConfiguredValue()) {
capAnvilCostItem = this.capAnvilCostFactory.getItem("Cap Anvil Cost");
maxAnvilCostItem = this.maxAnvilCostFactory.getItem(Material.EXPERIENCE_BOTTLE, "Max Anvil Cost");
capAnvilCostItem = this.capAnvilCost.getItem("Cap Anvil Cost");
maxAnvilCostItem = this.maxAnvilCost.getItem(Material.EXPERIENCE_BOTTLE, "Max Anvil Cost");
} else {
capAnvilCostItem = this.noCapRepairItem;
maxAnvilCostItem = this.noMaxCostItem;
@ -247,13 +323,36 @@ public class BasicConfigGui extends ChestGui implements ValueUpdatableGui {
pane.bindItem('U', unitRepairCostItem);
// item rename cost
GuiItem itemRenameCost = this.itemRenameCost.getItem(Material.NAME_TAG);
pane.bindItem('r', itemRenameCost);
GuiItem itemRenameCostItem = this.itemRenameCost.getItem(Material.NAME_TAG);
pane.bindItem('r', itemRenameCostItem);
// sacrifice illegal enchant cost
GuiItem illegalCostItem = this.sacrificeIllegalEnchantCost.getItem(Material.ENCHANTED_BOOK);
pane.bindItem('S', illegalCostItem);
// allow color code
GuiItem allowColorCodeItem = this.allowColorCode.getItem();
pane.bindItem('c', allowColorCodeItem);
// allow hex color
GuiItem allowHexColorItem = this.allowHexColor.getItem();
pane.bindItem('h', allowHexColorItem);
// True if player could place color
if(ConfigOptions.INSTANCE.getRenameColorPossible()){
// use permission for color
GuiItem permissionNeededItem = this.permissionNeededForColor.getItem();
pane.bindItem('p', permissionNeededItem);
// using color cost
GuiItem useColorCostItem = this.useOfColorCost.getItem(Material.EXPERIENCE_BOTTLE, "Use color");
pane.bindItem('P', useColorCostItem);
}else{
pane.bindItem('p', this.noPermissionNeededItem);
pane.bindItem('P', this.noColorCostItem);
}
update();
}

View file

@ -12,6 +12,7 @@ import io.delilaheve.util.ItemUtil.unitRepair
import org.bukkit.ChatColor
import org.bukkit.GameMode
import org.bukkit.Material
import org.bukkit.entity.HumanEntity
import org.bukkit.entity.Player
import org.bukkit.event.Event
import org.bukkit.event.EventHandler
@ -30,8 +31,11 @@ import xyz.alexcrea.cuanvil.dependency.protocolib.PacketManager
import xyz.alexcrea.cuanvil.group.ConflictType
import xyz.alexcrea.cuanvil.recipe.AnvilCustomRecipe
import xyz.alexcrea.cuanvil.util.UnitRepairUtil.getRepair
import java.util.regex.Matcher
import java.util.regex.Pattern
import kotlin.math.min
/**
* Listener for anvil events
*/
@ -79,7 +83,7 @@ class AnvilEventListener(private val packetManager: PacketManager) : Listener {
// Test rename lonely item
if (second == null) {
val resultItem = first.clone()
var anvilCost = handleRename(resultItem, inventory)
var anvilCost = handleRename(resultItem, inventory, player)
// Test/stop if nothing changed.
if (first == resultItem) {
@ -121,7 +125,7 @@ class AnvilEventListener(private val packetManager: PacketManager) : Listener {
// As calculatePenalty edit result, we need to calculate penalty after checking equality
anvilCost += calculatePenalty(first, second, resultItem)
// Calculate rename cost
anvilCost += handleRename(resultItem, inventory)
anvilCost += handleRename(resultItem, inventory, player)
// Finally, we set result
event.result = resultItem
@ -134,7 +138,7 @@ class AnvilEventListener(private val packetManager: PacketManager) : Listener {
val unitRepairAmount = first.getRepair(second)
if (unitRepairAmount != null) {
val resultItem = first.clone()
var anvilCost = handleRename(resultItem, inventory)
var anvilCost = handleRename(resultItem, inventory, player)
val repairAmount = resultItem.unitRepair(second.amount, unitRepairAmount)
if (repairAmount > 0) {
@ -159,20 +163,117 @@ class AnvilEventListener(private val packetManager: PacketManager) : Listener {
}
private fun handleRename(resultItem: ItemStack, inventory: AnvilInventory): Int {
private fun handleRename(resultItem: ItemStack, inventory: AnvilInventory, player: HumanEntity): Int {
// Rename item and add renaming cost
resultItem.itemMeta?.let {
val displayName = ChatColor.stripColor(it.displayName)
val inventoryName = ChatColor.stripColor(inventory.renameText)
if (!displayName.contentEquals(inventoryName)) {
it.setDisplayName(inventory.renameText)
resultItem.itemMeta = it
return ConfigOptions.itemRenameCost
var inventoryName = ChatColor.stripColor(inventory.renameText)
var sumCost = 0
var useColor = false
if(ConfigOptions.renameColorPossible){
val resultString = StringBuilder(inventoryName)
useColor = handleRenamingColor(resultString, player)
if(useColor) {
inventoryName = resultString.toString()
sumCost+= ConfigOptions.useOfColorCost
}
}
if ((!useColor && (!displayName.contentEquals(inventoryName))) || (useColor && !(it.displayName).contentEquals(inventoryName))) {
it.setDisplayName(inventoryName)
resultItem.itemMeta = it
sumCost+= ConfigOptions.itemRenameCost
}
return sumCost
}
return 0
}
private fun handleRenamingColor(textToColor: StringBuilder, player: HumanEntity): Boolean {
val usePermission = ConfigOptions.permissionNeededForColor
val canUseColorCode = ConfigOptions.allowColorCode && (!usePermission || player.hasPermission("ca.color.code"))
val canUseHexColor = ConfigOptions.allowHexadecimalColor && (!usePermission || player.hasPermission("ca.color.hex"))
if((!canUseColorCode) && (!canUseHexColor)) return false
var useColor = false
// Handle color code
if(canUseColorCode){
var nbReplacement = replaceAll(textToColor, "&", "§", 2)
nbReplacement -= 2 * replaceAll(textToColor, "§§", "&", 2)
if(nbReplacement > 0) useColor = true
}
if(canUseHexColor){
val nbReplacement = replaceHexToColor(textToColor, 7)
if(nbReplacement > 0) useColor = true
}
return useColor
}
/**
* Replace every instance of "from" to "to".
* @param builder The builder to replace the string from.
* @param from The source that should be replaced.
* @param to The string that should replace.
* @param endOffset Amount of character that should be ignored at the end.
* @return The number of replacement was that was done.
*/
private fun replaceAll(builder: java.lang.StringBuilder, from: String, to: String, endOffset: Int): Int {
var index = builder.indexOf(from)
var numberOfChanges = 0
while (index != -1 && index < builder.length - endOffset) {
builder.replace(index, index + from.length, to)
index += to.length
index = builder.indexOf(from, index)
numberOfChanges+=1
}
return numberOfChanges
}
val HEX_PATTERN: Pattern = Pattern.compile("#[A-Fa-f0-9]{6}") // pattern to find hexadecimal string
/**
* Replace every hex color formatted like #000000 to the minecraft format
* @param builder The builder to replace the hex color from.
* @param endOffset Amount of character that should be ignored at the end.
* @return The number of replacement was that was done.
*/
private fun replaceHexToColor(builder: StringBuilder, endOffset: Int): Int {
val matcher: Matcher = HEX_PATTERN.matcher(builder)
var numberOfChanges = 0
var startIndex = 0
while(matcher.find(startIndex)){
startIndex = matcher.start()
if(startIndex >= builder.length - endOffset) break
builder.replace(startIndex, startIndex + 1, "§x")
startIndex+=2
for (i in 0..5) {
builder.insert(startIndex, '§')
startIndex+=2
}
numberOfChanges+=1
}
return numberOfChanges
}
/**
* Event handler logic for when a player is trying to pull an item out of the anvil
*/
@ -322,8 +423,14 @@ class AnvilEventListener(private val packetManager: PacketManager) : Listener {
leftItem.itemMeta?.let { leftMeta ->
val leftName = leftMeta.displayName
output.itemMeta?.let {
// Rename cost
if (!leftName.contentEquals(it.displayName)) {
repairCost += ConfigOptions.itemRenameCost
// Color cost
if(it.displayName.contains('§')){
repairCost += ConfigOptions.useOfColorCost
}
}
}
}
@ -396,7 +503,7 @@ class AnvilEventListener(private val packetManager: PacketManager) : Listener {
/**
* Function to calculate work penalty of anvil work
* Also change result work penalty
* Also change result work penalty if right item is not null
*/
private fun calculatePenalty(left: ItemStack, right: ItemStack?, result: ItemStack): Int {
// Extracted From https://minecraft.fandom.com/wiki/Anvil_mechanics#Enchantment_equation
@ -409,10 +516,13 @@ class AnvilEventListener(private val packetManager: PacketManager) : Listener {
(right.itemMeta as? Repairable)?.repairCost ?: 0
}
// Try to set work penalty for the result item
result.itemMeta?.let {
(it as? Repairable)?.repairCost = leftPenalty * 2 + 1
result.itemMeta = it
// Try to set work penalty for the result item only if right item not null
if(right != null){
result.itemMeta?.let {
(it as? Repairable)?.repairCost = leftPenalty * 2 + 1
result.itemMeta = it
}
}
CustomAnvil.log(

View file

@ -10,87 +10,74 @@ import xyz.alexcrea.cuanvil.enchant.CAEnchantment
*/
object ConfigOptions {
// Path for limiting anvil cost
// ----------------------
// Path for config values
// ----------------------
const val CAP_ANVIL_COST = "limit_repair_cost"
// Path for max anvil cost value
const val MAX_ANVIL_COST = "limit_repair_value"
// Path for removing anvil cost limits
const val REMOVE_ANVIL_COST_LIMIT = "remove_repair_limit"
// Path for removing too expensive when unused
const val REPLACE_TOO_EXPENSIVE = "replace_too_expensive"
// Path for level cost on item repair
const val ITEM_REPAIR_COST = "item_repair_cost"
// Path for level cost on unit repair
const val UNIT_REPAIR_COST = "unit_repair_cost"
// Path for level cost on item renaming
const val ITEM_RENAME_COST = "item_rename_cost"
// Path for level cost on illegal enchantment on sacrifice
const val SACRIFICE_ILLEGAL_COST = "sacrifice_illegal_enchant_cost"
// Path for default enchantment limits
// Color related config
const val ALLOW_COLOR_CODE = "allow_color_code"
const val ALLOW_HEXADECIMAL_COLOR = "allow_hexadecimal_color"
const val PERMISSION_NEEDED_FOR_COLOR = "permission_needed_for_color"
const val USE_OF_COLOR_COST = "use_of_color_cost"
private const val DEFAULT_LIMIT_PATH = "default_limit"
// Root path for enchantment limits
const val ENCHANT_LIMIT_ROOT = "enchant_limits"
// Root path for enchantment values
const val ENCHANT_VALUES_ROOT = "enchant_values"
// Keys for specific enchantment values
private const val KEY_BOOK = "book"
private const val KEY_ITEM = "item"
// Debug logging toggle path
// Debug flag
private const val DEBUG_LOGGING = "debug_log"
// Debug verbose logging toggle path
private const val VERBOSE_DEBUG_LOGGING = "debug_log_verbose"
// ----------------------
// Default config values
// ----------------------
// Default value for limiting repair cost
const val DEFAULT_CAP_ANVIL_COST = false
// Default value for repair cost limit
const val DEFAULT_MAX_ANVIL_COST = 39
// Default for removing repair cost limits
const val DEFAULT_REMOVE_ANVIL_COST_LIMIT = false
// Default for removing repair cost limits
const val DEFAULT_REPLACE_TOO_EXPENSIVE = false
// Default value for level cost on item repair
const val DEFAULT_ITEM_REPAIR_COST = 2
// Default value for level cost per unit repair
const val DEFAULT_UNIT_REPAIR_COST = 1
// Default value for level cost on item renaming
const val DEFAULT_ITEM_RENAME_COST = 1
// Default value for level cost on illegal enchantment on sacrifice
const val DEFAULT_SACRIFICE_ILLEGAL_COST = 1
// Color related config
const val DEFAULT_ALLOW_COLOR_CODE = false
const val DEFAULT_ALLOW_HEXADECIMAL_COLOR = false
const val DEFAULT_PERMISSION_NEEDED_FOR_COLOR = true
const val DEFAULT_USE_OF_COLOR_COST = 0
// Default value for enchantment limits
private const val DEFAULT_ENCHANT_LIMIT = 5
// Default value for debug logging
// Debug flag
private const val DEFAULT_DEBUG_LOG = false
// Default value for debug logging
private const val DEFAULT_VERBOSE_DEBUG_LOG = false
// -------------
// Config Ranges
// -------------
// Valid range for repair cost limit
@JvmField
@ -108,6 +95,10 @@ object ConfigOptions {
@JvmField
val SACRIFICE_ILLEGAL_COST_RANGE = 0..1000
// Valid range for color use cost
@JvmField
val USE_OF_COLOR_COST_RANGE = 0..1000
// Valid range for an enchantment limit
@JvmField
val ENCHANT_LIMIT_RANGE = 1..255
@ -116,6 +107,10 @@ object ConfigOptions {
// Default value for an enchantment multiplier
private const val DEFAULT_ENCHANT_VALUE = 0
// -------------
// Get methods
// -------------
/**
* Whether to cap anvil costs
*/
@ -206,6 +201,53 @@ object ConfigOptions {
?: DEFAULT_SACRIFICE_ILLEGAL_COST
}
/**
* Allow usage of color code
*/
val allowColorCode: Boolean
get() {
return ConfigHolder.DEFAULT_CONFIG
.config
.getBoolean(ALLOW_COLOR_CODE, DEFAULT_ALLOW_COLOR_CODE)
}
/**
* Allow usage of hexadecimal color
*/
val allowHexadecimalColor: Boolean
get() {
return ConfigHolder.DEFAULT_CONFIG
.config
.getBoolean(ALLOW_HEXADECIMAL_COLOR, DEFAULT_ALLOW_HEXADECIMAL_COLOR)
}
/**
* If one of the color component is enabled
*/
val renameColorPossible: Boolean get() { return allowColorCode || allowHexadecimalColor }
/**
* If players need a permission to use color
*/
val permissionNeededForColor: Boolean
get() {
return ConfigHolder.DEFAULT_CONFIG
.config
.getBoolean(PERMISSION_NEEDED_FOR_COLOR, DEFAULT_PERMISSION_NEEDED_FOR_COLOR)
}
/**
* How many xp should use of color should cost
*/
val useOfColorCost: Int
get() {
return ConfigHolder.DEFAULT_CONFIG
.config
.getInt(USE_OF_COLOR_COST, DEFAULT_USE_OF_COLOR_COST)
.takeIf { it in USE_OF_COLOR_COST_RANGE }
?: DEFAULT_USE_OF_COLOR_COST
}
/**
* Default enchantment limit
*/

View file

@ -55,7 +55,24 @@ unit_repair_cost: 1
# Valid values include 0 to 1000
sacrifice_illegal_enchant_cost: 1
# Default limit to apply to any enchants missing from override_limits
# Allow using color code and hexadecimal color.
#
# Color code are prefixed by "&" and hexadecimal color by "#".
# Color code will not be applied if it colors nothing. "&&" can be used to write "&".
allow_color_code: false
allow_hexadecimal_color: false
# Toggle if color should only be applicable if the player a certain permission.
#
# permission are "ca.color.code" for use of color code and "ca.color.hex" for use of hexadecimal color.
permission_needed_for_color: true
# Xp cost if the player use color in the items name on rename.
#
# Valid values include 0 to 1000.
use_of_color_cost: 0
# Default limit to apply to any enchants missing from enchant_limits
#
# Valid values include 1 to 1000
default_limit: 5

View file

@ -39,6 +39,14 @@ permissions:
ca.config.edit:
default: op
description: Allow administrator to edit the plugin's config in game
# color permissions
ca.color.code:
default: op
description: Allow player to use color code if permission is required (toggleable)
ca.color.hex:
default: op
description: Allow player to use hexadecimal color if permission is required (toggleable)
# 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