diff --git a/defaultconfigs/1.18/config.yml b/defaultconfigs/1.18/config.yml index eb45a8a..872ea2e 100644 --- a/defaultconfigs/1.18/config.yml +++ b/defaultconfigs/1.18/config.yml @@ -77,6 +77,18 @@ allow_color_code: false allow_hexadecimal_color: false allow_minimessage: false +# This enables restricting color code for player having specific permission +# It requires allow_color_code enabled for... obvious reasons +# +# For example: if player want to use "&aHello" it will be required that the player has +# the permission "ca.color.code.a" as he used the color code "a" +# In general permission to give to the player is "ca.color.code.[code]" +# where [code] is the color code you wish to allow the player +# +# It is kinda of useless when minimessage is supported as players would be able to bypass +# that using the equivalent minimessage tag +per_color_code_permission: 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. diff --git a/defaultconfigs/1.21.11/config.yml b/defaultconfigs/1.21.11/config.yml index c4500a8..bbfcb88 100644 --- a/defaultconfigs/1.21.11/config.yml +++ b/defaultconfigs/1.21.11/config.yml @@ -79,6 +79,18 @@ allow_color_code: false allow_hexadecimal_color: false allow_minimessage: false +# This enables restricting color code for player having specific permission +# It requires allow_color_code enabled for... obvious reasons +# +# For example: if player want to use "&aHello" it will be required that the player has +# the permission "ca.color.code.a" as he used the color code "a" +# In general permission to give to the player is "ca.color.code.[code]" +# where [code] is the color code you wish to allow the player +# +# It is kinda of useless when minimessage is supported as players would be able to bypass +# that using the equivalent minimessage tag +per_color_code_permission: 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. diff --git a/defaultconfigs/1.21.9/config.yml b/defaultconfigs/1.21.9/config.yml index 91a796b..0d4f810 100644 --- a/defaultconfigs/1.21.9/config.yml +++ b/defaultconfigs/1.21.9/config.yml @@ -77,6 +77,18 @@ allow_color_code: false allow_hexadecimal_color: false allow_minimessage: false +# This enables restricting color code for player having specific permission +# It requires allow_color_code enabled for... obvious reasons +# +# For example: if player want to use "&aHello" it will be required that the player has +# the permission "ca.color.code.a" as he used the color code "a" +# In general permission to give to the player is "ca.color.code.[code]" +# where [code] is the color code you wish to allow the player +# +# It is kinda of useless when minimessage is supported as players would be able to bypass +# that using the equivalent minimessage tag +per_color_code_permission: 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. diff --git a/defaultconfigs/1.21/config.yml b/defaultconfigs/1.21/config.yml index 99606ba..24df643 100644 --- a/defaultconfigs/1.21/config.yml +++ b/defaultconfigs/1.21/config.yml @@ -77,6 +77,18 @@ allow_color_code: false allow_hexadecimal_color: false allow_minimessage: false +# This enables restricting color code for player having specific permission +# It requires allow_color_code enabled for... obvious reasons +# +# For example: if player want to use "&aHello" it will be required that the player has +# the permission "ca.color.code.a" as he used the color code "a" +# In general permission to give to the player is "ca.color.code.[code]" +# where [code] is the color code you wish to allow the player +# +# It is kinda of useless when minimessage is supported as players would be able to bypass +# that using the equivalent minimessage tag +per_color_code_permission: 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. diff --git a/src/main/kotlin/io/delilaheve/util/ConfigOptions.kt b/src/main/kotlin/io/delilaheve/util/ConfigOptions.kt index b761784..b6aa3d7 100644 --- a/src/main/kotlin/io/delilaheve/util/ConfigOptions.kt +++ b/src/main/kotlin/io/delilaheve/util/ConfigOptions.kt @@ -2,7 +2,6 @@ package io.delilaheve.util import io.delilaheve.CustomAnvil import io.delilaheve.util.EnchantmentUtil.enchantmentName -import org.bukkit.Material import org.bukkit.NamespacedKey import xyz.alexcrea.cuanvil.config.ConfigHolder import xyz.alexcrea.cuanvil.config.WorkPenaltyType @@ -45,6 +44,8 @@ object ConfigOptions { const val PERMISSION_NEEDED_FOR_COLOR = "permission_needed_for_color" const val USE_OF_COLOR_COST = "use_of_color_cost" + const val PER_COLOR_CODE_PERMISSION = "per_color_code_permission" + // Work penalty config const val WORK_PENALTY_ROOT = "work_penalty" const val WORK_PENALTY_INCREASE = "shared_increase" @@ -100,6 +101,8 @@ object ConfigOptions { const val DEFAULT_PERMISSION_NEEDED_FOR_COLOR = true const val DEFAULT_USE_OF_COLOR_COST = 0 + const val DEFAULT_PER_COLOR_CODE_PERMISSION = false + // Debug flag private const val DEFAULT_DEBUG_LOG = false private const val DEFAULT_VERBOSE_DEBUG_LOG = false @@ -297,6 +300,16 @@ object ConfigOptions { .getBoolean(PERMISSION_NEEDED_FOR_COLOR, DEFAULT_PERMISSION_NEEDED_FOR_COLOR) } + /** + * Should each color code require a permission + */ + val usePerColorCodePermission: Boolean + get() { + return ConfigHolder.DEFAULT_CONFIG + .config + .getBoolean(PER_COLOR_CODE_PERMISSION, DEFAULT_PER_COLOR_CODE_PERMISSION) + } + /** * How many xp should use of color should cost */ diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilColorUtil.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilColorUtil.kt index 5996d9f..25c4268 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilColorUtil.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilColorUtil.kt @@ -1,5 +1,6 @@ package xyz.alexcrea.cuanvil.util +import io.delilaheve.util.ConfigOptions import net.kyori.adventure.text.Component import org.bukkit.permissions.Permissible import java.util.regex.Matcher @@ -13,7 +14,8 @@ object AnvilColorUtil { class ColorPermissions( val canUseColorCode: Boolean, val canUseHexColor: Boolean, - val canUseMinimessage: Boolean + val canUseMinimessage: Boolean, + val permissible: Permissible, // source of the permission. tried to avoid needing it but meh ) { fun allowed(): Boolean { return canUseColorCode || canUseHexColor || canUseMinimessage @@ -36,7 +38,8 @@ object AnvilColorUtil { return ColorPermissions( canUseColorCode = false, canUseHexColor = false, - canUseMinimessage = false + canUseMinimessage = false, + player, ) val canUseColorCode = @@ -54,7 +57,7 @@ object AnvilColorUtil { useType.hexColorPerm )) - return ColorPermissions(canUseColorCode, canUseHexColor, canUseMinimessage) + return ColorPermissions(canUseColorCode, canUseHexColor, canUseMinimessage, player) } /** @@ -70,9 +73,11 @@ object AnvilColorUtil { allowMinimessage: Boolean, useType: ColorUseType ): Component? { - val permission = calculatePermissions(player, usePermission, + val permission = calculatePermissions( + player, usePermission, allowColorCode, allowHexadecimalColor, allowMinimessage, - useType) + useType + ) return handleColor(textToColorText, permission) } @@ -82,9 +87,10 @@ object AnvilColorUtil { */ fun handleColor( textToColorText: String, - permission: ColorPermissions - ): Component? { - if(!permission.allowed()) return null + permission: ColorPermissions, + + ): Component? { + if (!permission.allowed()) return null val textToColor = StringBuilder(textToColorText) var useColor = false @@ -93,7 +99,12 @@ object AnvilColorUtil { var nbReplacement = replaceAll(textToColor, "&", "§", 2) nbReplacement -= 2 * replaceAll(textToColor, "§§", "&", 2) - if (nbReplacement > 0) useColor = true + if (nbReplacement > 0) { + useColor = true + + if (ConfigOptions.usePerColorCodePermission) + filterPermissibleColorCode(textToColor, permission.permissible) + } } if (permission.canUseHexColor) { @@ -104,23 +115,38 @@ object AnvilColorUtil { val previousStr = textToColor.toString() var result: Component = MiniMessageUtil.legacy_mm.deserialize(previousStr) - if(permission.canUseMinimessage) { + if (permission.canUseMinimessage) { // we dance with formats here val toMinimessage = MiniMessageUtil.mm.serialize(result) val hackySolution = toMinimessage.replace("\\<", "<") val fromMinimessage = MiniMessageUtil.mm.deserialize(hackySolution) val asPlain = MiniMessageUtil.plain_text_mm.serialize(fromMinimessage) - if(previousStr != asPlain){ + if (previousStr != asPlain) { useColor = true result = fromMinimessage } } - return if(useColor) result + return if (useColor) result else null } + private fun filterPermissibleColorCode(textToColor: StringBuilder, player: Permissible) { + var index = 0 + while (true) { + index = textToColor.indexOf('§', index) + if (index == -1 || index == textToColor.length - 1) return + + val next = textToColor[index + 1] + // check permission for this color + if(!player.hasPermission("ca.color.code.$next")) + textToColor.replace(index, index + 1, "&") + + index++ + } + } + /** * Best effort to revert a component to the smallest allowed string * that would result in it getting closest as possible to handleColor @@ -131,12 +157,12 @@ object AnvilColorUtil { component: Component?, permission: ColorPermissions ): String? { - if(!permission.allowed() || component == null) return null + if (!permission.allowed() || component == null) return null val transformed = MiniMessageUtil.mm.serialize(component) val plainTransform = MiniMessageUtil.plain_text_mm.serialize(component) - if(transformed == plainTransform) return null - if(permission.onlyMinimessage()){ + if (transformed == plainTransform) return null + if (permission.onlyMinimessage()) { return transformed } @@ -164,10 +190,10 @@ object AnvilColorUtil { val hackySolution = hackySolutionStb.toString() val result: String = - if(permission.canUseMinimessage) hackySolution + if (permission.canUseMinimessage) hackySolution else MiniMessageUtil.mm.stripTags(hackySolution) - return if(result == plainTransform) null + return if (result == plainTransform) null else result } @@ -209,7 +235,7 @@ object AnvilColorUtil { while (matcher.find(startIndex)) { startIndex = matcher.start() if (startIndex >= builder.length - endOffset) break //HOW AND WHERE WOULD THIS HAPPEN ????? - if(checkTag && isInTag(builder, startIndex)) { + if (checkTag && isInTag(builder, startIndex)) { startIndex += 1 // Avoid infinite loop continue } @@ -237,7 +263,7 @@ object AnvilColorUtil { var rightIndex = left.lastIndexOf(">") // last < do not exist or is before last > - if(leftIndex == -1 || rightIndex > leftIndex) return false + if (leftIndex == -1 || rightIndex > leftIndex) return false val right = builder.slice(index..