From 9912da869c5619fe6ed9aa64ea128d13bcf25b91 Mon Sep 17 00:00:00 2001 From: alexcrea Date: Sun, 19 Oct 2025 16:45:45 +0200 Subject: [PATCH 1/8] add minimessage for color and decoration only --- README.md | 7 +-- build.gradle.kts | 3 ++ defaultconfigs/1.18/config.yml | 2 + defaultconfigs/1.21.9/config.yml | 2 + defaultconfigs/1.21/config.yml | 2 + .../io/delilaheve/util/ConfigOptions.kt | 16 ++++++- .../cuanvil/listener/PrepareAnvilListener.kt | 2 +- .../alexcrea/cuanvil/util/AnvilColorUtil.kt | 48 ++++++++++++++++--- .../cuanvil/util/AnvilLoreEditUtil.kt | 6 ++- .../cuanvil/util/config/LoreEditConfigUtil.kt | 2 + .../cuanvil/util/config/LoreEditType.kt | 13 +++++ src/main/resources/config.yml | 2 + 12 files changed, 91 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 829eeb0..492d6f6 100644 --- a/README.md +++ b/README.md @@ -41,9 +41,10 @@ ca.config.edit: Allow administrator to edit the plugin's config in game # Bellow permissions also require some config change to allow usage of features # usage of these permission is toggleable in basic config gui or config.yml -# Permissions related to use of color -ca.color.code: Allow player to use color code if enabled (toggleable) -ca.color.hex: Allow player to use hexadecimal color if enabled (toggleable) +# Permissions related to use of color and minimessage +ca.color.code: Allow player to use color code on rename if enabled (toggleable) +ca.color.hex: Allow player to use hexadecimal color on rename if enabled (toggleable) +ca.color.minimessage: Allow player to use minimessage formating on rename if enabled (toggleable) # Permissions related to edition of the lore ca.lore_edit.book: Allow player to edit lore via book and quil if enabled (toggleable) diff --git a/build.gradle.kts b/build.gradle.kts index 675c4ec..ef848c7 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -35,6 +35,9 @@ dependencies { // Spigot api compileOnly("org.spigotmc:spigot-api:1.18-R0.1-SNAPSHOT") + // minimessage + implementation("net.kyori:adventure-text-minimessage:4.25.0") + // Gui library val inventoryFramework = "xyz.alexcrea.cuanvil.inventoryframework:IF-CustomAnvil:0.10.18.2" implementation(inventoryFramework) diff --git a/defaultconfigs/1.18/config.yml b/defaultconfigs/1.18/config.yml index fbe43f7..c558ec3 100644 --- a/defaultconfigs/1.18/config.yml +++ b/defaultconfigs/1.18/config.yml @@ -59,8 +59,10 @@ sacrifice_illegal_enchant_cost: 1 # # Color code are prefixed by "&" and hexadecimal color by "#". # Color code will not be applied if it colors nothing. "&&" can be used to write "&". +# For minimessage search for minimessage formating https://docs.papermc.io/adventure/minimessage/format/ allow_color_code: false allow_hexadecimal_color: false +allow_minimessage: false # Toggle if color should only be applicable if the player a certain permission. # diff --git a/defaultconfigs/1.21.9/config.yml b/defaultconfigs/1.21.9/config.yml index f6817ba..9964fe8 100644 --- a/defaultconfigs/1.21.9/config.yml +++ b/defaultconfigs/1.21.9/config.yml @@ -59,8 +59,10 @@ sacrifice_illegal_enchant_cost: 1 # # Color code are prefixed by "&" and hexadecimal color by "#". # Color code will not be applied if it colors nothing. "&&" can be used to write "&". +# For minimessage search for minimessage formating https://docs.papermc.io/adventure/minimessage/format/ allow_color_code: false allow_hexadecimal_color: false +allow_minimessage: false # Toggle if color should only be applicable if the player a certain permission. # diff --git a/defaultconfigs/1.21/config.yml b/defaultconfigs/1.21/config.yml index d6e76bf..b6f0ba0 100644 --- a/defaultconfigs/1.21/config.yml +++ b/defaultconfigs/1.21/config.yml @@ -59,8 +59,10 @@ sacrifice_illegal_enchant_cost: 1 # # Color code are prefixed by "&" and hexadecimal color by "#". # Color code will not be applied if it colors nothing. "&&" can be used to write "&". +# For minimessage search for minimessage formating https://docs.papermc.io/adventure/minimessage/format/ allow_color_code: false allow_hexadecimal_color: false +allow_minimessage: false # Toggle if color should only be applicable if the player a certain permission. # diff --git a/src/main/kotlin/io/delilaheve/util/ConfigOptions.kt b/src/main/kotlin/io/delilaheve/util/ConfigOptions.kt index 2a8360f..877de4c 100644 --- a/src/main/kotlin/io/delilaheve/util/ConfigOptions.kt +++ b/src/main/kotlin/io/delilaheve/util/ConfigOptions.kt @@ -38,6 +38,7 @@ object ConfigOptions { // Color related config const val ALLOW_COLOR_CODE = "allow_color_code" const val ALLOW_HEXADECIMAL_COLOR = "allow_hexadecimal_color" + const val ALLOW_MINIMESSAGE = "allow_minimessage" const val PERMISSION_NEEDED_FOR_COLOR = "permission_needed_for_color" const val USE_OF_COLOR_COST = "use_of_color_cost" @@ -87,13 +88,14 @@ object ConfigOptions { const val DEFAULT_ITEM_RENAME_COST = 1 const val DEFAULT_SACRIFICE_ILLEGAL_COST = 1 - const val DEFAULT_ADD_BOOK_ENCHANTMENT_AS_STORED_ENCHANTMENT = false; + const val DEFAULT_ADD_BOOK_ENCHANTMENT_AS_STORED_ENCHANTMENT = false const val DEFAULT_ENCHANT_COUNT_LIMIT = -1 // Color related config const val DEFAULT_ALLOW_COLOR_CODE = false const val DEFAULT_ALLOW_HEXADECIMAL_COLOR = false + const val DEFAULT_ALLOW_MINIMESSAGE = false const val DEFAULT_PERMISSION_NEEDED_FOR_COLOR = true const val DEFAULT_USE_OF_COLOR_COST = 0 @@ -269,12 +271,22 @@ object ConfigOptions { .getBoolean(ALLOW_HEXADECIMAL_COLOR, DEFAULT_ALLOW_HEXADECIMAL_COLOR) } + /** + * Allow usage of minimessage formating + */ + val allowMinimessage: Boolean + get() { + return ConfigHolder.DEFAULT_CONFIG + .config + .getBoolean(ALLOW_MINIMESSAGE, DEFAULT_ALLOW_MINIMESSAGE) + } + /** * If one of the color component is enabled */ val renameColorPossible: Boolean get() { - return allowColorCode || allowHexadecimalColor + return allowColorCode || allowHexadecimalColor || allowHexadecimalColor } /** diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/listener/PrepareAnvilListener.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/listener/PrepareAnvilListener.kt index 8eefc97..5ba1dfa 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/listener/PrepareAnvilListener.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/listener/PrepareAnvilListener.kt @@ -196,7 +196,7 @@ class PrepareAnvilListener : Listener { useColor = AnvilColorUtil.handleColor( resultString, player, ConfigOptions.permissionNeededForColor, - ConfigOptions.allowColorCode, ConfigOptions.allowHexadecimalColor, + ConfigOptions.allowColorCode, ConfigOptions.allowHexadecimalColor, ConfigOptions.allowMinimessage, AnvilColorUtil.ColorUseType.RENAME ) diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilColorUtil.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilColorUtil.kt index 277a8d1..91fc31d 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilColorUtil.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilColorUtil.kt @@ -1,5 +1,9 @@ package xyz.alexcrea.cuanvil.util +import net.kyori.adventure.text.minimessage.MiniMessage +import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver +import net.kyori.adventure.text.minimessage.tag.standard.StandardTags +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer import org.bukkit.permissions.Permissible import java.util.regex.Matcher import java.util.regex.Pattern @@ -8,9 +12,19 @@ object AnvilColorUtil { private val HEX_PATTERN: Pattern = Pattern.compile("#[A-Fa-f0-9]{6}") // pattern to find hexadecimal string private val TRANSFORMED_HEX_PATTERN = Pattern.compile("§x(§[0-9a-fA-F]){6}") // pattern to find minecraft hex string + //TODO use only things compatible with legacy formating + private val mm = MiniMessage.builder() + .tags(TagResolver.resolver( + StandardTags.color(), + StandardTags.decorations())) + .build() + private val legacymm = LegacyComponentSerializer.legacySection() + /** + * //TODO rework on 2.x.x use (return) component and not legacy string + * * Color a stringbuilder object depending on allowed color type and player permissions on color use type - * @return if the stringbuilder was changed and color applied + * @return if the stringbuilder was changed and color applied or if minimessage formating was applied */ fun handleColor( textToColor: StringBuilder, @@ -18,9 +32,10 @@ object AnvilColorUtil { usePermission: Boolean, allowColorCode: Boolean, allowHexadecimalColor: Boolean, + allowMinimessage: Boolean, useType: ColorUseType ): Boolean { - if (!allowColorCode && !allowHexadecimalColor) return false + if (!allowColorCode && !allowHexadecimalColor && !allowMinimessage) return false val canUseColorCode = allowColorCode && (!usePermission || useType.colorCodePerm == null || player.hasPermission( @@ -30,12 +45,16 @@ object AnvilColorUtil { allowHexadecimalColor && (!usePermission || useType.hexColorPerm == null || player.hasPermission( useType.hexColorPerm )) + val canUseMinimessage = + allowMinimessage && (!usePermission || useType.minimessagePerm == null || player.hasPermission( + useType.minimessagePerm + )) if ((!canUseColorCode) && (!canUseHexColor)) return false var useColor = false // Handle color code - if (canUseColorCode) { + if (canUseColorCode) { // maybe should use LegacyComponentSerializer ? var nbReplacement = replaceAll(textToColor, "&", "§", 2) nbReplacement -= 2 * replaceAll(textToColor, "§§", "&", 2) @@ -48,6 +67,22 @@ object AnvilColorUtil { if (nbReplacement > 0) useColor = true } + if(canUseMinimessage) { + val previousStr = textToColor.toString() + + // we dance with formats here + val fromLegacy = legacymm.deserialize(previousStr) + val toMinimessage = mm.serialize(fromLegacy) + val hackySolution = toMinimessage.replace("\\<", "<") + val fromMinimessage = mm.deserialize(hackySolution) + val toLegacy = legacymm.serialize(fromMinimessage) + + if(previousStr != toLegacy){ + useColor = true + textToColor.replace(0, textToColor.length, toLegacy) + } + } + return useColor } @@ -177,10 +212,11 @@ object AnvilColorUtil { enum class ColorUseType( val colorCodePerm: String?, - val hexColorPerm: String? + val hexColorPerm: String?, + val minimessagePerm: String? ) { - RENAME("ca.color.code", "ca.color.hex"), - LORE_EDIT(null, null) + RENAME("ca.color.code", "ca.color.hex", "ca.color.minimessage"), + LORE_EDIT(null, null, null) } } \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilLoreEditUtil.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilLoreEditUtil.kt index dd0da1e..598a7ce 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilLoreEditUtil.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilLoreEditUtil.kt @@ -243,9 +243,10 @@ object AnvilLoreEditUtil { private fun colorLines(player: Permissible, lines: ArrayList, editType: LoreEditType): Int { val canUseHex = editType.allowHexColor val canUseColorCode = editType.allowColorCode + val minimessage = editType.allowMinimessage val colorCost = editType.useColorCost - // Now handle color of each lines + // Handle color and minimessage of each lines var hasUsedColor = false for ((index, line) in lines.withIndex()) { val coloredLine = StringBuilder(line) @@ -253,7 +254,8 @@ object AnvilLoreEditUtil { val lineUsedColor = AnvilColorUtil.handleColor( coloredLine, player, - false, canUseColorCode, canUseHex, + false, + canUseColorCode, canUseHex, minimessage, AnvilColorUtil.ColorUseType.LORE_EDIT ) diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/config/LoreEditConfigUtil.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/config/LoreEditConfigUtil.kt index f5758dc..2a2fa3b 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/config/LoreEditConfigUtil.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/util/config/LoreEditConfigUtil.kt @@ -17,6 +17,7 @@ object LoreEditConfigUtil { // Color configs path const val ALLOW_COLOR_CODE = "allow_color_code" const val ALLOW_HEX_COLOR = "allow_hexadecimal_color" + const val ALLOW_MINIMESSAGE = "allow_minimessage" const val USE_COLOR_COST = "use_cost" const val REMOVE_COLOR_ON_LORE_REMOVE = "remove_color_on_remove" @@ -42,6 +43,7 @@ object LoreEditConfigUtil { // Color configs defaults const val DEFAULT_ALLOW_COLOR_CODE = true const val DEFAULT_ALLOW_HEX_COLOR = true + const val DEFAULT_ALLOW_MINIMESSAGE = true const val DEFAULT_USE_COLOR_COST = 0 const val DEFAULT_REMOVE_COLOR_ON_LORE_REMOVE = false diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/config/LoreEditType.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/config/LoreEditType.kt index ed5ef1b..bb1632e 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/config/LoreEditType.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/util/config/LoreEditType.kt @@ -3,8 +3,10 @@ package xyz.alexcrea.cuanvil.util.config import xyz.alexcrea.cuanvil.util.AnvilUseType import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil.ALLOW_COLOR_CODE import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil.ALLOW_HEX_COLOR +import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil.ALLOW_MINIMESSAGE import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil.DEFAULT_ALLOW_COLOR_CODE import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil.DEFAULT_ALLOW_HEX_COLOR +import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil.DEFAULT_ALLOW_MINIMESSAGE import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil.DEFAULT_REMOVE_COLOR_COST import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil.DEFAULT_REMOVE_COLOR_ON_LORE_REMOVE import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil.DEFAULT_USE_COLOR_COST @@ -100,6 +102,17 @@ enum class LoreEditType( .getBoolean("${rootPath}.$ALLOW_HEX_COLOR", DEFAULT_ALLOW_HEX_COLOR) } + /** + * Allow usage of minimessage on lore add + */ + val allowMinimessage: Boolean + get() { + if (!isAppend) throw IllegalStateException("Can only call with an append edit type") + return CONFIG + .config + .getBoolean("${rootPath}.$ALLOW_MINIMESSAGE", DEFAULT_ALLOW_MINIMESSAGE) + } + /** * Cost when using either color code and hex color on lore add */ diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index a0f0876..3ba35b9 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -59,8 +59,10 @@ sacrifice_illegal_enchant_cost: 1 # # Color code are prefixed by "&" and hexadecimal color by "#". # Color code will not be applied if it colors nothing. "&&" can be used to write "&". +# For minimessage search for minimessage formating https://docs.papermc.io/adventure/minimessage/format/ allow_color_code: false allow_hexadecimal_color: false +allow_minimessage: false # Toggle if color should only be applicable if the player a certain permission. # From 8411b21d1c6cb000ac43fb42266453ef3eac70bb Mon Sep 17 00:00:00 2001 From: alexcrea Date: Sun, 19 Oct 2025 17:01:30 +0200 Subject: [PATCH 2/8] forgot some config --- defaultconfigs/1.18/config.yml | 8 +++++--- defaultconfigs/1.21.9/config.yml | 14 ++++++++------ defaultconfigs/1.21/config.yml | 6 ++++-- src/main/resources/config.yml | 7 +++++-- 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/defaultconfigs/1.18/config.yml b/defaultconfigs/1.18/config.yml index c558ec3..df156b7 100644 --- a/defaultconfigs/1.18/config.yml +++ b/defaultconfigs/1.18/config.yml @@ -59,7 +59,7 @@ sacrifice_illegal_enchant_cost: 1 # # Color code are prefixed by "&" and hexadecimal color by "#". # Color code will not be applied if it colors nothing. "&&" can be used to write "&". -# For minimessage search for minimessage formating https://docs.papermc.io/adventure/minimessage/format/ +# For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ allow_color_code: false allow_hexadecimal_color: false allow_minimessage: false @@ -303,9 +303,10 @@ lore_edit: # # Color code are prefixed by "&" and hexadecimal color by "#" # Color code will not be applied if it colors nothing. "&&" can be used to write "&" + # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ allow_color_code: true allow_hexadecimal_color: true - use_cost: 0 + allow_minimessage: true remove: # If removing lore using book & quil is enabled @@ -346,10 +347,11 @@ lore_edit: # # Color code are prefixed by "&" and hexadecimal color by "#" # Color code will not be applied if it colors nothing. "&&" can be used to write "&" + # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ allow_color_code: true allow_hexadecimal_color: true + allow_minimessage: true color_use_cost: 0 - use_cost: 0 remove_line: # If removing lore line using paper is enabled diff --git a/defaultconfigs/1.21.9/config.yml b/defaultconfigs/1.21.9/config.yml index 9964fe8..401884d 100644 --- a/defaultconfigs/1.21.9/config.yml +++ b/defaultconfigs/1.21.9/config.yml @@ -315,10 +315,11 @@ lore_edit: # # Color code are prefixed by "&" and hexadecimal color by "#" # Color code will not be applied if it colors nothing. "&&" can be used to write "&" + # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ allow_color_code: true allow_hexadecimal_color: true - use_cost: 0 - + allow_minimessage: true + remove: # If removing lore using book & quil is enabled enabled: false @@ -336,13 +337,13 @@ lore_edit: remove_color_on_remove: true # Cost of replacing colors remove_color_cost: 0 - + paper: # Permission is ca.lore_edit.paper use_permission: true # what order should the lines should get added/removed (start/end, if invalid or not present will be end) order: end - + append_line: # If adding lore line using paper is enabled enabled: false @@ -358,11 +359,12 @@ lore_edit: # # Color code are prefixed by "&" and hexadecimal color by "#" # Color code will not be applied if it colors nothing. "&&" can be used to write "&" + # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ allow_color_code: true allow_hexadecimal_color: true + allow_minimessage: true color_use_cost: 0 - use_cost: 0 - + remove_line: # If removing lore line using paper is enabled enabled: false diff --git a/defaultconfigs/1.21/config.yml b/defaultconfigs/1.21/config.yml index b6f0ba0..0e013ea 100644 --- a/defaultconfigs/1.21/config.yml +++ b/defaultconfigs/1.21/config.yml @@ -303,9 +303,10 @@ lore_edit: # # Color code are prefixed by "&" and hexadecimal color by "#" # Color code will not be applied if it colors nothing. "&&" can be used to write "&" + # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ allow_color_code: true allow_hexadecimal_color: true - use_cost: 0 + allow_minimessage: true remove: # If removing lore using book & quil is enabled @@ -346,10 +347,11 @@ lore_edit: # # Color code are prefixed by "&" and hexadecimal color by "#" # Color code will not be applied if it colors nothing. "&&" can be used to write "&" + # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ allow_color_code: true allow_hexadecimal_color: true + allow_minimessage: true color_use_cost: 0 - use_cost: 0 remove_line: # If removing lore line using paper is enabled diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 3ba35b9..1c8c010 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -303,9 +303,10 @@ lore_edit: # # Color code are prefixed by "&" and hexadecimal color by "#" # Color code will not be applied if it colors nothing. "&&" can be used to write "&" + # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ allow_color_code: true allow_hexadecimal_color: true - use_cost: 0 + allow_minimessage: true remove: # If removing lore using book & quil is enabled @@ -329,7 +330,7 @@ lore_edit: # Permission is ca.lore_edit.paper use_permission: true # what order should the lines should get added/removed (start/end, if invalid or not present will be end) - order: "end" + order: end append_line: # If adding lore line using paper is enabled @@ -346,8 +347,10 @@ lore_edit: # # Color code are prefixed by "&" and hexadecimal color by "#" # Color code will not be applied if it colors nothing. "&&" can be used to write "&" + # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ allow_color_code: true allow_hexadecimal_color: true + allow_minimessage: true color_use_cost: 0 remove_line: From c9e41aceb6314c978bf2371f3379a7f64121acb2 Mon Sep 17 00:00:00 2001 From: alexcrea Date: Mon, 20 Oct 2025 11:25:43 +0200 Subject: [PATCH 3/8] some refractor --- README.md | 4 +- .../cuanvil/listener/PrepareAnvilListener.kt | 25 ++++++----- .../alexcrea/cuanvil/util/AnvilColorUtil.kt | 42 +++++++------------ .../cuanvil/util/AnvilLoreEditUtil.kt | 17 +++----- .../alexcrea/cuanvil/util/MiniMessageUtil.kt | 18 ++++++++ src/main/resources/plugin.yml | 3 ++ 6 files changed, 56 insertions(+), 53 deletions(-) create mode 100644 src/main/kotlin/xyz/alexcrea/cuanvil/util/MiniMessageUtil.kt diff --git a/README.md b/README.md index 492d6f6..cc868c5 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ the plugin can be downloaded on - Display XP cost instead of "too expensive" when above level 40. (see below for more information) - Can handle some custom enchantment plugins (see below for more information) - Gui to configure the plugin in game. -- Support of color code and hexadecimal color +- Support use of color code, hexadecimal color and minimessage for color/decoration - (Experimental) Folia support (gui do not work) --- ### Permissions: @@ -44,7 +44,7 @@ ca.config.edit: Allow administrator to edit the plugin's config in game # Permissions related to use of color and minimessage ca.color.code: Allow player to use color code on rename if enabled (toggleable) ca.color.hex: Allow player to use hexadecimal color on rename if enabled (toggleable) -ca.color.minimessage: Allow player to use minimessage formating on rename if enabled (toggleable) +ca.rename.minimessage: Allow player to use minimessage formating on rename if enabled (toggleable) (only legacy compatible at the time) # Permissions related to edition of the lore ca.lore_edit.book: Allow player to edit lore via book and quil if enabled (toggleable) diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/listener/PrepareAnvilListener.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/listener/PrepareAnvilListener.kt index 5ba1dfa..17d5d0d 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/listener/PrepareAnvilListener.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/listener/PrepareAnvilListener.kt @@ -186,24 +186,23 @@ class PrepareAnvilListener : Listener { private fun handleRename(resultItem: ItemStack, inventory: AnvilInventory, player: HumanEntity): Int { // Can be null - var inventoryName = ChatColor.stripColor(inventory.renameText) + var renameText = ChatColor.stripColor(inventory.renameText) var sumCost = 0 var useColor = false - if (ConfigOptions.renameColorPossible && inventoryName != null) { - val resultString = StringBuilder(inventoryName) - - useColor = AnvilColorUtil.handleColor( - resultString, player, + if (ConfigOptions.renameColorPossible && renameText != null) { + val component = AnvilColorUtil.handleColor( + renameText, player, ConfigOptions.permissionNeededForColor, ConfigOptions.allowColorCode, ConfigOptions.allowHexadecimalColor, ConfigOptions.allowMinimessage, AnvilColorUtil.ColorUseType.RENAME ) - if (useColor) { - inventoryName = resultString.toString() + if (component != null) { + renameText = MiniMessageUtil.legacy_mm.serialize(component) sumCost += ConfigOptions.useOfColorCost + useColor = true } } @@ -214,8 +213,8 @@ class PrepareAnvilListener : Listener { else if (useColor) it.displayName else ChatColor.stripColor(it.displayName) - if (!displayName.contentEquals(inventoryName)) { - it.setDisplayName(inventoryName) + if (!displayName.contentEquals(renameText)) { + it.setDisplayName(renameText) resultItem.itemMeta = it sumCost += ConfigOptions.itemRenameCost @@ -233,10 +232,10 @@ class PrepareAnvilListener : Listener { ) { val newEnchants = first.findEnchantments() .combineWith(second.findEnchantments(), first, player) - var hasChanged = !isIdentical(first.findEnchantments(), newEnchants); + var hasChanged = !isIdentical(first.findEnchantments(), newEnchants) val resultItem = first.clone() - var anvilCost = 0; + var anvilCost = 0 if(hasChanged){ resultItem.setEnchantmentsUnsafe(newEnchants) // Calculate enchantment cost @@ -248,7 +247,7 @@ class PrepareAnvilListener : Listener { // we only need to be concerned with repair when neither item is a book val repaired = resultItem.repairFrom(first, second) anvilCost += if (repaired) ConfigOptions.itemRepairCost else 0 - hasChanged = hasChanged || repaired; + hasChanged = hasChanged || repaired } // Test/stop if nothing changed. diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilColorUtil.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilColorUtil.kt index 91fc31d..2629d1f 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilColorUtil.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilColorUtil.kt @@ -1,9 +1,6 @@ package xyz.alexcrea.cuanvil.util -import net.kyori.adventure.text.minimessage.MiniMessage -import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver -import net.kyori.adventure.text.minimessage.tag.standard.StandardTags -import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer +import net.kyori.adventure.text.Component import org.bukkit.permissions.Permissible import java.util.regex.Matcher import java.util.regex.Pattern @@ -12,30 +9,20 @@ object AnvilColorUtil { private val HEX_PATTERN: Pattern = Pattern.compile("#[A-Fa-f0-9]{6}") // pattern to find hexadecimal string private val TRANSFORMED_HEX_PATTERN = Pattern.compile("§x(§[0-9a-fA-F]){6}") // pattern to find minecraft hex string - //TODO use only things compatible with legacy formating - private val mm = MiniMessage.builder() - .tags(TagResolver.resolver( - StandardTags.color(), - StandardTags.decorations())) - .build() - private val legacymm = LegacyComponentSerializer.legacySection() - /** - * //TODO rework on 2.x.x use (return) component and not legacy string - * * Color a stringbuilder object depending on allowed color type and player permissions on color use type * @return if the stringbuilder was changed and color applied or if minimessage formating was applied */ fun handleColor( - textToColor: StringBuilder, + textToColorText: String, player: Permissible, usePermission: Boolean, allowColorCode: Boolean, allowHexadecimalColor: Boolean, allowMinimessage: Boolean, useType: ColorUseType - ): Boolean { - if (!allowColorCode && !allowHexadecimalColor && !allowMinimessage) return false + ): Component? { + if (!allowColorCode && !allowHexadecimalColor && !allowMinimessage) return null val canUseColorCode = allowColorCode && (!usePermission || useType.colorCodePerm == null || player.hasPermission( @@ -50,8 +37,9 @@ object AnvilColorUtil { useType.minimessagePerm )) - if ((!canUseColorCode) && (!canUseHexColor)) return false + if (!canUseColorCode && !canUseHexColor && !canUseMinimessage) return null + val textToColor = StringBuilder(textToColorText) var useColor = false // Handle color code if (canUseColorCode) { // maybe should use LegacyComponentSerializer ? @@ -67,23 +55,23 @@ object AnvilColorUtil { if (nbReplacement > 0) useColor = true } + val previousStr = textToColor.toString() + var result: Component = MiniMessageUtil.legacy_mm.deserialize(previousStr) if(canUseMinimessage) { - val previousStr = textToColor.toString() - // we dance with formats here - val fromLegacy = legacymm.deserialize(previousStr) - val toMinimessage = mm.serialize(fromLegacy) + val toMinimessage = MiniMessageUtil.mm.serialize(result) val hackySolution = toMinimessage.replace("\\<", "<") - val fromMinimessage = mm.deserialize(hackySolution) - val toLegacy = legacymm.serialize(fromMinimessage) + val fromMinimessage = MiniMessageUtil.mm.deserialize(hackySolution) + val toLegacy = MiniMessageUtil.legacy_mm.serialize(fromMinimessage) if(previousStr != toLegacy){ useColor = true - textToColor.replace(0, textToColor.length, toLegacy) + result = fromMinimessage } } - return useColor + return if(useColor) result + else null } /** @@ -215,7 +203,7 @@ object AnvilColorUtil { val hexColorPerm: String?, val minimessagePerm: String? ) { - RENAME("ca.color.code", "ca.color.hex", "ca.color.minimessage"), + RENAME("ca.color.code", "ca.color.hex", "ca.rename.minimessage"), LORE_EDIT(null, null, null) } diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilLoreEditUtil.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilLoreEditUtil.kt index 598a7ce..0f0d69d 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilLoreEditUtil.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilLoreEditUtil.kt @@ -249,27 +249,22 @@ object AnvilLoreEditUtil { // Handle color and minimessage of each lines var hasUsedColor = false for ((index, line) in lines.withIndex()) { - val coloredLine = StringBuilder(line) - - val lineUsedColor = AnvilColorUtil.handleColor( - coloredLine, + val component = AnvilColorUtil.handleColor( + line, player, false, canUseColorCode, canUseHex, minimessage, AnvilColorUtil.ColorUseType.LORE_EDIT ) - if (lineUsedColor) { + if (component != null) { hasUsedColor = true - lines[index] = coloredLine.toString() + lines[index] = MiniMessageUtil.legacy_mm.serialize(component) } } - return if (hasUsedColor) { - colorCost - } else { - 0 - } + return if (hasUsedColor) colorCost + else 0 } fun uncolorLines(player: Permissible, lines: ArrayList, editType: LoreEditType): Int { diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/MiniMessageUtil.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/MiniMessageUtil.kt new file mode 100644 index 0000000..10500e8 --- /dev/null +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/util/MiniMessageUtil.kt @@ -0,0 +1,18 @@ +package xyz.alexcrea.cuanvil.util + +import net.kyori.adventure.text.minimessage.MiniMessage +import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver +import net.kyori.adventure.text.minimessage.tag.standard.StandardTags +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer + +object MiniMessageUtil { + + val mm = MiniMessage.builder() + .tags(TagResolver.resolver( + StandardTags.color(), + StandardTags.decorations())) + .build() + + val legacy_mm = LegacyComponentSerializer.legacySection() + +} diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 0e58169..9449f8b 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -46,6 +46,9 @@ permissions: ca.color.hex: default: op description: Allow player to use hexadecimal color if enabled (toggleable) + ca.rename.minimessage: + default: op + description: Allow player to use minimessage formating on rename if enabled (toggleable) (only legacy compatible at the time) # lore edit permissions ca.lore_edit.book: default: op From 2967d500eb7d846810fcb16b0b3c3b5091bad053 Mon Sep 17 00:00:00 2001 From: alexcrea <42614139+alexcrea@users.noreply.github.com> Date: Thu, 23 Oct 2025 08:32:33 +0200 Subject: [PATCH 4/8] use correct condition Co-authored-by: Illyrius <28700752+illyrius666@users.noreply.github.com> --- src/main/kotlin/io/delilaheve/util/ConfigOptions.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/io/delilaheve/util/ConfigOptions.kt b/src/main/kotlin/io/delilaheve/util/ConfigOptions.kt index 877de4c..afb009f 100644 --- a/src/main/kotlin/io/delilaheve/util/ConfigOptions.kt +++ b/src/main/kotlin/io/delilaheve/util/ConfigOptions.kt @@ -286,7 +286,7 @@ object ConfigOptions { */ val renameColorPossible: Boolean get() { - return allowColorCode || allowHexadecimalColor || allowHexadecimalColor + return allowColorCode || allowHexadecimalColor || allowMinimessage } /** From 11f7bf8602573c7603012cde1cc3e7acb6e1926d Mon Sep 17 00:00:00 2001 From: alexcrea Date: Thu, 23 Oct 2025 14:26:11 +0200 Subject: [PATCH 5/8] progress on using pure component in paper --- defaultconfigs/1.18/config.yml | 34 +++- defaultconfigs/1.21.9/config.yml | 34 +++- defaultconfigs/1.21/config.yml | 34 +++- nms/nms-common/build.gradle.kts | 31 +++- .../cuanvil/dependency/util/PaperSpigtUtil.kt | 102 ++++++++++++ nms/v1_21R6/build.gradle.kts | 2 +- .../cuanvil/update/PluginSetDefault.java | 1 - .../cuanvil/command/EditConfigExecutor.kt | 4 +- .../cuanvil/dependency/DependencyManager.kt | 25 +-- .../cuanvil/listener/AnvilResultListener.kt | 22 ++- .../alexcrea/cuanvil/util/AnvilColorUtil.kt | 149 +++++++++++++----- .../cuanvil/util/AnvilLoreEditUtil.kt | 143 +++++++++++------ .../alexcrea/cuanvil/util/MiniMessageUtil.kt | 23 ++- .../cuanvil/util/config/LoreEditConfigUtil.kt | 2 - .../cuanvil/util/config/LoreEditType.kt | 22 +-- src/main/resources/config.yml | 36 ++++- .../alexcrea/cuanvil/anvil/LoreEditTests.java | 5 +- 17 files changed, 502 insertions(+), 167 deletions(-) create mode 100644 nms/nms-common/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/util/PaperSpigtUtil.kt diff --git a/defaultconfigs/1.18/config.yml b/defaultconfigs/1.18/config.yml index df156b7..692ee2d 100644 --- a/defaultconfigs/1.18/config.yml +++ b/defaultconfigs/1.18/config.yml @@ -304,6 +304,8 @@ lore_edit: # Color code are prefixed by "&" and hexadecimal color by "#" # Color code will not be applied if it colors nothing. "&&" can be used to write "&" # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ + # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin + # but any global tag will be allowed later when v2 release allow_color_code: true allow_hexadecimal_color: true allow_minimessage: true @@ -321,10 +323,21 @@ lore_edit: shared_additive: false # If removing the lore consume the book & quil do_consume: false - # If the color should get back to color code or hex format - remove_color_on_remove: true # Cost of replacing colors remove_color_cost: 0 + # Allowed some color and tags to be reverted to plain text + # Custom anvil will prioritise format that result is a smaller resulting text + # Note that not allowing certain format will lead to some lost of color or tags. + # If configuration are exact as append appending this book should result in the exact same color + # + # Color code will be prefixed by "&" and hexadecimal color by "#". + # If color code is allowed, "&" in the text will get converted to "&&" + # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ + # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin + # but any global tag will be allowed later when v2 release + allow_color_code: true + allow_hexadecimal_color: true + allow_minimessage: true paper: # Permission is ca.lore_edit.paper @@ -348,6 +361,8 @@ lore_edit: # Color code are prefixed by "&" and hexadecimal color by "#" # Color code will not be applied if it colors nothing. "&&" can be used to write "&" # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ + # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin + # but any global tag will be allowed later when v2 release allow_color_code: true allow_hexadecimal_color: true allow_minimessage: true @@ -364,10 +379,21 @@ lore_edit: shared_additive: false # If removing the lore line consume the paper do_consume: false - # If the color should get back to color code or hex format - remove_color_on_remove: true # Cost of replacing colors remove_color_cost: 0 + # Allowed some color and tags to be reverted to plain text + # Custom anvil will prioritise format that result is a smaller resulting text + # Note that not allowing certain format will lead to some lost of color or tags. + # If configuration are exact as append appending this paper should result in the exact same color + # + # Color code will be prefixed by "&" and hexadecimal color by "#". + # If color code is allowed, "&" in the text will get converted to "&&" + # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ + # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin + # but any global tag will be allowed later when v2 release + allow_color_code: true + allow_hexadecimal_color: true + allow_minimessage: true # Whether to show debug logging debug_log: false diff --git a/defaultconfigs/1.21.9/config.yml b/defaultconfigs/1.21.9/config.yml index 401884d..028c401 100644 --- a/defaultconfigs/1.21.9/config.yml +++ b/defaultconfigs/1.21.9/config.yml @@ -316,6 +316,8 @@ lore_edit: # Color code are prefixed by "&" and hexadecimal color by "#" # Color code will not be applied if it colors nothing. "&&" can be used to write "&" # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ + # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin + # but any global tag will be allowed later when v2 release allow_color_code: true allow_hexadecimal_color: true allow_minimessage: true @@ -333,10 +335,21 @@ lore_edit: shared_additive: false # If removing the lore consume the book & quil do_consume: false - # If the color should get back to color code or hex format - remove_color_on_remove: true # Cost of replacing colors remove_color_cost: 0 + # Allowed some color and tags to be reverted to plain text + # Custom anvil will prioritise format that result is a smaller resulting text + # Note that not allowing certain format will lead to some lost of color or tags. + # If configuration are exact as append appending this book should result in the exact same color + # + # Color code will be prefixed by "&" and hexadecimal color by "#". + # If color code is allowed, "&" in the text will get converted to "&&" + # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ + # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin + # but any global tag will be allowed later when v2 release + allow_color_code: true + allow_hexadecimal_color: true + allow_minimessage: true paper: # Permission is ca.lore_edit.paper @@ -360,6 +373,8 @@ lore_edit: # Color code are prefixed by "&" and hexadecimal color by "#" # Color code will not be applied if it colors nothing. "&&" can be used to write "&" # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ + # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin + # but any global tag will be allowed later when v2 release allow_color_code: true allow_hexadecimal_color: true allow_minimessage: true @@ -376,10 +391,21 @@ lore_edit: shared_additive: false # If removing the lore line consume the paper do_consume: false - # If the color should get back to color code or hex format - remove_color_on_remove: true # Cost of replacing colors remove_color_cost: 0 + # Allowed some color and tags to be reverted to plain text + # Custom anvil will prioritise format that result is a smaller resulting text + # Note that not allowing certain format will lead to some lost of color or tags. + # If configuration are exact as append appending this paper should result in the exact same color + # + # Color code will be prefixed by "&" and hexadecimal color by "#". + # If color code is allowed, "&" in the text will get converted to "&&" + # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ + # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin + # but any global tag will be allowed later when v2 release + allow_color_code: true + allow_hexadecimal_color: true + allow_minimessage: true # Whether to show debug logging debug_log: false diff --git a/defaultconfigs/1.21/config.yml b/defaultconfigs/1.21/config.yml index 0e013ea..fe655c2 100644 --- a/defaultconfigs/1.21/config.yml +++ b/defaultconfigs/1.21/config.yml @@ -304,6 +304,8 @@ lore_edit: # Color code are prefixed by "&" and hexadecimal color by "#" # Color code will not be applied if it colors nothing. "&&" can be used to write "&" # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ + # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin + # but any global tag will be allowed later when v2 release allow_color_code: true allow_hexadecimal_color: true allow_minimessage: true @@ -321,10 +323,21 @@ lore_edit: shared_additive: false # If removing the lore consume the book & quil do_consume: false - # If the color should get back to color code or hex format - remove_color_on_remove: true # Cost of replacing colors remove_color_cost: 0 + # Allowed some color and tags to be reverted to plain text + # Custom anvil will prioritise format that result is a smaller resulting text + # Note that not allowing certain format will lead to some lost of color or tags. + # If configuration are exact as append appending this book should result in the exact same color + # + # Color code will be prefixed by "&" and hexadecimal color by "#". + # If color code is allowed, "&" in the text will get converted to "&&" + # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ + # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin + # but any global tag will be allowed later when v2 release + allow_color_code: true + allow_hexadecimal_color: true + allow_minimessage: true paper: # Permission is ca.lore_edit.paper @@ -348,6 +361,8 @@ lore_edit: # Color code are prefixed by "&" and hexadecimal color by "#" # Color code will not be applied if it colors nothing. "&&" can be used to write "&" # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ + # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin + # but any global tag will be allowed later when v2 release allow_color_code: true allow_hexadecimal_color: true allow_minimessage: true @@ -364,10 +379,21 @@ lore_edit: shared_additive: false # If removing the lore line consume the paper do_consume: false - # If the color should get back to color code or hex format - remove_color_on_remove: true # Cost of replacing colors remove_color_cost: 0 + # Allowed some color and tags to be reverted to plain text + # Custom anvil will prioritise format that result is a smaller resulting text + # Note that not allowing certain format will lead to some lost of color or tags. + # If configuration are exact as append appending this paper should result in the exact same color + # + # Color code will be prefixed by "&" and hexadecimal color by "#". + # If color code is allowed, "&" in the text will get converted to "&&" + # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ + # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin + # but any global tag will be allowed later when v2 release + allow_color_code: true + allow_hexadecimal_color: true + allow_minimessage: true # Whether to show debug logging debug_log: false diff --git a/nms/nms-common/build.gradle.kts b/nms/nms-common/build.gradle.kts index 964b321..6088e77 100644 --- a/nms/nms-common/build.gradle.kts +++ b/nms/nms-common/build.gradle.kts @@ -1,10 +1,35 @@ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + group = rootProject.group version = rootProject.version +plugins { + id("io.papermc.paperweight.userdev") +} + dependencies { - // Spigot api - compileOnly("org.spigotmc:spigot-api:1.18-R0.1-SNAPSHOT") + // Used for nms + paperweight.paperDevBundle("1.21.10-R0.1-SNAPSHOT") // Protocolib compileOnly("net.dmulloy2:ProtocolLib:5.4.0") -} \ No newline at end of file +} + +repositories { + maven("https://repo.papermc.io/repository/maven-public/") +} + +// Set target version +tasks.withType().configureEach { + sourceCompatibility = "21" + targetCompatibility = "21" + + options.encoding = "UTF-8" +} + +kotlin { + compilerOptions { + apiVersion.set(org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_0) + jvmTarget.set(JvmTarget.JVM_21) + } +} diff --git a/nms/nms-common/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/util/PaperSpigtUtil.kt b/nms/nms-common/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/util/PaperSpigtUtil.kt new file mode 100644 index 0000000..3f709c7 --- /dev/null +++ b/nms/nms-common/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/util/PaperSpigtUtil.kt @@ -0,0 +1,102 @@ +package xyz.alexcrea.cuanvil.dependency.util + +import net.kyori.adventure.text.Component +import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer +import org.bukkit.inventory.ItemStack +import org.bukkit.inventory.meta.ItemMeta + +// Mostly made for paper, spigot and folia support +@Suppress("DEPRECATION") +object PlatformUtil { + + private fun hasClass(className: String): Boolean { + try { + Class.forName(className) + return true + } catch (_: ClassNotFoundException) { + return false + } + } + + private fun hasMethod(clazz: Class<*>, name: String, vararg parameterTypes: Class<*>): Boolean { + try { + clazz.getDeclaredMethod(name, *parameterTypes) + return true + } catch (_: NoSuchMethodException) { + return false + } + } + + val isPaper = hasClass("com.destroystokyo.paper.PaperConfig") || + hasClass("io.papermc.paper.configuration.Configuration") + + val isFolia = hasClass("io.papermc.paper.threadedregions.RegionizedServer") + + private val legacy_mm = LegacyComponentSerializer.legacySection() + + // Lore + fun ItemMeta.componentLore(): MutableList { + val lore: List? + if(isPaper){ + lore = this.lore() + } else { + val legacyLores = this.lore ?: return ArrayList() + + lore = ArrayList(legacyLores.size) + for (legacyLore in legacyLores) { + lore.add(legacy_mm.deserialize(legacyLore)) + } + } + + return lore ?: ArrayList() + } + + fun ItemMeta.setComponentLore(lore: List) { + if(isPaper){ + this.lore(lore) + } else { + val legacyLore = ArrayList(lore.size) + for (component in lore) { + legacyLore.add(if(component == null) null + else legacy_mm.serialize(component)) + } + + this.lore = legacyLore + } + } + + // Display name + private val useCustomName = hasMethod(ItemStack::class.java, "customName") + + fun ItemMeta.componentDisplayName(): Component? { + if(useCustomName){ + if(!this.hasCustomName()) return null + return this.customName() + }else if(isPaper){ + if(!this.hasDisplayName()) return null + return this.displayName() + } else { + if(!this.hasDisplayName()) return null + + val legacy = this.displayName + return legacy_mm.deserialize(legacy) + } + } + + fun ItemMeta.setComponentDisplayName(component: Component?) { + if(useCustomName){ + this.customName(component) + }else if(isPaper){ + this.displayName(component) + } else { + if(component == null){ + this.setDisplayName(null) + return + } + + val legacy = legacy_mm.serialize(component) + this.setDisplayName(legacy) + } + } + +} diff --git a/nms/v1_21R6/build.gradle.kts b/nms/v1_21R6/build.gradle.kts index f124fdd..3665d74 100644 --- a/nms/v1_21R6/build.gradle.kts +++ b/nms/v1_21R6/build.gradle.kts @@ -11,7 +11,7 @@ dependencies { implementation(project(":nms:nms-common")) // Used for nms - paperweight.paperDevBundle("1.21.9-R0.1-SNAPSHOT") + paperweight.paperDevBundle("1.21.10-R0.1-SNAPSHOT") } repositories { diff --git a/src/main/java/xyz/alexcrea/cuanvil/update/PluginSetDefault.java b/src/main/java/xyz/alexcrea/cuanvil/update/PluginSetDefault.java index 363bd6a..f41842d 100644 --- a/src/main/java/xyz/alexcrea/cuanvil/update/PluginSetDefault.java +++ b/src/main/java/xyz/alexcrea/cuanvil/update/PluginSetDefault.java @@ -48,7 +48,6 @@ public class PluginSetDefault { nbSet += trySetDefault(config, path + ALLOW_HEX_COLOR, DEFAULT_ALLOW_HEX_COLOR); nbSet += trySetDefault(config, path + USE_COLOR_COST, DEFAULT_USE_COLOR_COST); } else { - nbSet += trySetDefault(config, path + REMOVE_COLOR_ON_LORE_REMOVE, DEFAULT_REMOVE_COLOR_ON_LORE_REMOVE); nbSet += trySetDefault(config, path + REMOVE_COLOR_COST, DEFAULT_REMOVE_COLOR_COST); } } diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/command/EditConfigExecutor.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/command/EditConfigExecutor.kt index 85761d9..f90f765 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/command/EditConfigExecutor.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/command/EditConfigExecutor.kt @@ -5,7 +5,7 @@ import org.bukkit.command.Command import org.bukkit.command.CommandExecutor import org.bukkit.command.CommandSender import org.bukkit.entity.HumanEntity -import xyz.alexcrea.cuanvil.dependency.DependencyManager +import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil import xyz.alexcrea.cuanvil.gui.config.MainConfigGui import xyz.alexcrea.cuanvil.gui.util.GuiGlobalActions @@ -16,7 +16,7 @@ class EditConfigExecutor : CommandExecutor { sender.sendMessage(GuiGlobalActions.NO_EDIT_PERM) return false } - if(DependencyManager.isFolia){ + if(PlatformUtil.isFolia){ sender.sendMessage("§cIt look like you are using Folia. Sadly Custom Anvil do not support Config gui for Folia.") sender.sendMessage("§eIt is may come in a future version.") sender.sendMessage("") diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/DependencyManager.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/DependencyManager.kt index 4c8e9f6..66a9aa5 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/DependencyManager.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/dependency/DependencyManager.kt @@ -2,10 +2,10 @@ package xyz.alexcrea.cuanvil.dependency import com.willfp.eco.core.gui.player import io.delilaheve.CustomAnvil +import net.kyori.adventure.text.Component import org.bukkit.Bukkit import org.bukkit.ChatColor import org.bukkit.entity.HumanEntity -import org.bukkit.entity.Player import org.bukkit.event.inventory.InventoryClickEvent import org.bukkit.event.inventory.PrepareAnvilEvent import org.bukkit.inventory.AnvilInventory @@ -24,13 +24,14 @@ import xyz.alexcrea.cuanvil.dependency.plugins.* import xyz.alexcrea.cuanvil.dependency.scheduler.BukkitScheduler import xyz.alexcrea.cuanvil.dependency.scheduler.FoliaScheduler import xyz.alexcrea.cuanvil.dependency.scheduler.TaskScheduler +import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil +import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil.componentLore import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener.Companion.ANVIL_OUTPUT_SLOT import xyz.alexcrea.cuanvil.util.AnvilUseType import java.util.logging.Level object DependencyManager { - var isFolia: Boolean = false lateinit var scheduler: TaskScheduler lateinit var packetManager: PacketManager var externGuiTester: ExternGuiTester? = null @@ -50,8 +51,7 @@ object DependencyManager { val pluginManager = Bukkit.getPluginManager() // Bukkit or Paper scheduler ? - isFolia = testIsFolia() - scheduler = if (isFolia) { + scheduler = if (PlatformUtil.isFolia) { CustomAnvil.instance.logger.info("Folia detected... Custom Anvil Folia support is experimental. issues are more likely to happens.") FoliaScheduler() @@ -305,15 +305,15 @@ object DependencyManager { return bypass } - fun stripLore(item: ItemStack): ArrayList { - val lore = ArrayList() + fun stripLore(item: ItemStack): MutableList { val dummy = item.clone() enchantmentSquaredCompatibility?.stripLore(dummy) - val itemLore = dummy.itemMeta!!.lore - if (itemLore != null) lore.addAll(itemLore) + val itemLore = dummy.itemMeta?.componentLore() ?: return ArrayList() + val lore = ArrayList() + lore.addAll(itemLore) return lore } @@ -321,13 +321,4 @@ object DependencyManager { enchantmentSquaredCompatibility?.updateLore(item) } - private fun testIsFolia(): Boolean { - try { - Class.forName("io.papermc.paper.threadedregions.RegionizedServer") - return true - } catch (e: ClassNotFoundException) { - return false - } - } - } diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/listener/AnvilResultListener.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/listener/AnvilResultListener.kt index 64e43d1..db2dfb0 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/listener/AnvilResultListener.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/listener/AnvilResultListener.kt @@ -17,6 +17,7 @@ import org.bukkit.inventory.InventoryView import org.bukkit.inventory.ItemStack import org.bukkit.inventory.meta.BookMeta import xyz.alexcrea.cuanvil.dependency.DependencyManager +import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil.setComponentDisplayName import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener.Companion.ANVIL_INPUT_LEFT import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener.Companion.ANVIL_INPUT_RIGHT import xyz.alexcrea.cuanvil.listener.PrepareAnvilListener.Companion.ANVIL_OUTPUT_SLOT @@ -30,6 +31,7 @@ import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil import xyz.alexcrea.cuanvil.util.config.LoreEditType import java.util.* import java.util.concurrent.atomic.AtomicInteger +import java.util.concurrent.atomic.AtomicReference import kotlin.math.min class AnvilResultListener : Listener { @@ -397,8 +399,6 @@ class AnvilResultListener : Listener { if (output != AnvilLoreEditUtil.handleLoreRemoveByBook(player, leftItem, xpCost)) return false // fill book meta - val meta = leftItem.itemMeta - if (meta == null || !meta.hasLore()) return false val lore = DependencyManager.stripLore(leftItem) if (lore.isEmpty()) return false @@ -443,10 +443,10 @@ class AnvilResultListener : Listener { if (Material.PAPER != rightItem.type) return false val paperMeta = rightItem.itemMeta ?: return false - val editType = AnvilLoreEditUtil.paperLoreEditIsAppend(leftItem, rightItem) ?: return false + val editTypeIsAppend = AnvilLoreEditUtil.paperLoreEditIsAppend(leftItem, rightItem) ?: return false val xpCost = AtomicInteger() - if (editType) { + if (editTypeIsAppend) { if (output != AnvilLoreEditUtil.handleLoreAppendByPaper(player, leftItem, rightItem, xpCost)) return false val paperCopy: ItemStack? @@ -456,7 +456,7 @@ class AnvilResultListener : Listener { // Remove custom name to paper paperCopy = rightItem.clone() paperCopy.amount = 1 - paperMeta.setDisplayName(null) + paperMeta.setComponentDisplayName(null) paperCopy.itemMeta = paperMeta } @@ -489,20 +489,18 @@ class AnvilResultListener : Listener { rightClone = null } else { val removeEnd = LoreEditConfigUtil.paperLoreOrderIsEnd - var line = if (removeEnd) lore[lore.size - 1] + val line = if (removeEnd) lore[lore.size - 1] else lore[0] - // Overkill but uncolor the line - val tempList = ArrayList(1) - tempList.add(line) - AnvilLoreEditUtil.uncolorLines(player, tempList, LoreEditType.REMOVE_PAPER) - line = tempList[0] + // uncolor the line + val ref = AtomicReference(line) + AnvilLoreEditUtil.uncolorLine(player, ref, LoreEditType.REMOVE_PAPER) rightClone = rightItem.clone() rightClone.amount = 1 val resultMeta = rightClone.itemMeta ?: return false - resultMeta.setDisplayName(line) + resultMeta.setComponentDisplayName(ref.get()) rightClone.itemMeta = resultMeta } diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilColorUtil.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilColorUtil.kt index 2629d1f..0abcaaf 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilColorUtil.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilColorUtil.kt @@ -9,20 +9,33 @@ object AnvilColorUtil { private val HEX_PATTERN: Pattern = Pattern.compile("#[A-Fa-f0-9]{6}") // pattern to find hexadecimal string private val TRANSFORMED_HEX_PATTERN = Pattern.compile("§x(§[0-9a-fA-F]){6}") // pattern to find minecraft hex string - /** - * Color a stringbuilder object depending on allowed color type and player permissions on color use type - * @return if the stringbuilder was changed and color applied or if minimessage formating was applied - */ - fun handleColor( - textToColorText: String, + class ColorPermissions( + val canUseColorCode: Boolean, + val canUseHexColor: Boolean, + val canUseMinimessage: Boolean + ) { + fun allowed(): Boolean { + return canUseColorCode || canUseHexColor || canUseMinimessage + } + + fun onlyMinimessage(): Boolean { + return canUseMinimessage && !canUseColorCode && !canUseHexColor + } + } + + fun calculatePermissions( player: Permissible, usePermission: Boolean, allowColorCode: Boolean, allowHexadecimalColor: Boolean, allowMinimessage: Boolean, - useType: ColorUseType - ): Component? { - if (!allowColorCode && !allowHexadecimalColor && !allowMinimessage) return null + useType: ColorUseType): ColorPermissions { + if (!allowColorCode && !allowHexadecimalColor && !allowMinimessage) + return ColorPermissions( + canUseColorCode = false, + canUseHexColor = false, + canUseMinimessage = false + ) val canUseColorCode = allowColorCode && (!usePermission || useType.colorCodePerm == null || player.hasPermission( @@ -37,19 +50,49 @@ object AnvilColorUtil { useType.minimessagePerm )) - if (!canUseColorCode && !canUseHexColor && !canUseMinimessage) return null + return ColorPermissions(canUseColorCode, canUseHexColor, canUseMinimessage) + } + + /** + * Color a string depending on allowed color type, color use type and player permissions + * @return colored component or null if nothing has been colored + */ + fun handleColor( + textToColorText: String, + player: Permissible, + usePermission: Boolean, + allowColorCode: Boolean, + allowHexadecimalColor: Boolean, + allowMinimessage: Boolean, + useType: ColorUseType + ): Component? { + val permission = calculatePermissions(player, usePermission, + allowColorCode, allowHexadecimalColor, allowMinimessage, + useType) + return handleColor(textToColorText, permission) + } + + /** + * Color a string depending on permitted use + * @return colored component or null if nothing has been colored + */ + fun handleColor( + textToColorText: String, + permission: ColorPermissions + ): Component? { + if(!permission.allowed()) return null val textToColor = StringBuilder(textToColorText) var useColor = false // Handle color code - if (canUseColorCode) { // maybe should use LegacyComponentSerializer ? + if (permission.canUseColorCode) { // maybe should use LegacyComponentSerializer ? var nbReplacement = replaceAll(textToColor, "&", "§", 2) nbReplacement -= 2 * replaceAll(textToColor, "§§", "&", 2) if (nbReplacement > 0) useColor = true } - if (canUseHexColor) { + if (permission.canUseHexColor) { val nbReplacement = replaceHexToColor(textToColor, 7) if (nbReplacement > 0) useColor = true @@ -57,8 +100,8 @@ object AnvilColorUtil { val previousStr = textToColor.toString() var result: Component = MiniMessageUtil.legacy_mm.deserialize(previousStr) - if(canUseMinimessage) { - // we dance with formats here + if(permission.canUseMinimessage) { + // we dance with formats here TODO maybe extract, if possible, only the "text" part and use it for compare with previous as tag would be missing? val toMinimessage = MiniMessageUtil.mm.serialize(result) val hackySolution = toMinimessage.replace("\\<", "<") val fromMinimessage = MiniMessageUtil.mm.deserialize(hackySolution) @@ -75,46 +118,72 @@ object AnvilColorUtil { } /** - * Revert a stringbuilder to a state where applying handleColor with the same options would give the same result - * @return if the stringbuilder was changed and color unapplied + * Best effort to revert a component to the smallest allowed string + * that would result in it getting closest as possible to handleColor + * with current set of color type, color use type and player permissions + * @return the new component if had any change. null otherwise */ - fun revertColor( - colorToText: StringBuilder, + fun revertColorSmallest( + component: Component, player: Permissible, usePermission: Boolean, allowColorCode: Boolean, + allowMinimessage: Boolean, allowHexadecimalColor: Boolean, useType: ColorUseType - ): Boolean { - if (!allowColorCode && !allowHexadecimalColor) return false + ): String? { + val permission = calculatePermissions(player, usePermission, + allowColorCode, allowHexadecimalColor, allowMinimessage, + useType) + return revertColorSmallest(component, permission) + } - val canUseColorCode = - allowColorCode && (!usePermission || useType.colorCodePerm == null || player.hasPermission( - useType.colorCodePerm - )) - val canUseHexColor = - allowHexadecimalColor && (!usePermission || useType.hexColorPerm == null || player.hasPermission( - useType.hexColorPerm - )) + /** + * Best effort to revert a component to the smallest allowed string + * that would result in it getting closest as possible to handleColor + * with current set of permitted use + * @return a new component if had any change. null otherwise + */ + fun revertColorSmallest( + component: Component?, + permission: ColorPermissions + ): String? { + if(!permission.allowed() || component == null) return null - if ((!canUseColorCode) && (!canUseHexColor)) return false - var hasReversed = false + val transformed = MiniMessageUtil.mm.serialize(component) + val plainTransform = MiniMessageUtil.plain_text_mm.serialize(component) + if(transformed == plainTransform) return null + if(permission.onlyMinimessage()){ + return transformed + } + + // smol dance so we transform the component that may contain other tag into only decoration & color for legacy + val coloredMessage = MiniMessageUtil.color_only_mm.deserialize(transformed) + val legacyMessage = StringBuilder(MiniMessageUtil.legacy_mm.serialize(coloredMessage)) // Reverse hex pattern - if (canUseHexColor) { - val nbReplacement = replaceColorToHex(colorToText, 14) - - if (nbReplacement > 0) hasReversed = true + if (permission.canUseHexColor) { + replaceColorToHex(legacyMessage, 14) } - if (canUseColorCode) { - replaceAll(colorToText, "&", "&&", 1) - val nbReplacement = replaceAll(colorToText, "§", "&", 2) - - if (nbReplacement > 0) hasReversed = true + // Reverse color pattern + if (permission.canUseColorCode) { + replaceAll(legacyMessage, "&", "&&", 1) + replaceAll(legacyMessage, "§", "&", 2) } - return hasReversed + // In case we still has some § around by lack of permission we need to convert it back from legacy + // In other word it's time for dance #3 + val fromLegacy = MiniMessageUtil.legacy_mm.deserialize(legacyMessage.toString()) + val middleGround = MiniMessageUtil.color_only_mm.serialize(fromLegacy) + val hackySolution = middleGround.replace("\\<", "<") + + val result: String = + if(permission.canUseMinimessage) hackySolution + else MiniMessageUtil.mm.stripTags(hackySolution) + + return if(result == plainTransform) null + else result } /** diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilLoreEditUtil.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilLoreEditUtil.kt index 0f0d69d..4135df7 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilLoreEditUtil.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilLoreEditUtil.kt @@ -1,13 +1,18 @@ package xyz.alexcrea.cuanvil.util +import net.kyori.adventure.text.Component import org.bukkit.entity.HumanEntity import org.bukkit.inventory.ItemStack import org.bukkit.inventory.meta.BookMeta import org.bukkit.permissions.Permissible import xyz.alexcrea.cuanvil.dependency.DependencyManager +import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil.componentLore +import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil.setComponentLore import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil import xyz.alexcrea.cuanvil.util.config.LoreEditType +import java.util.* import java.util.concurrent.atomic.AtomicInteger +import java.util.concurrent.atomic.AtomicReference object AnvilLoreEditUtil { @@ -32,24 +37,24 @@ object AnvilLoreEditUtil { val result = first.clone() val meta = result.itemMeta ?: return null - val lore = if (meta.hasLore()) { - ArrayList(meta.lore!!) - } else ArrayList() + val lore = meta.componentLore() val page = book.pages[0] val lines = ArrayList(page.split("\n")) - val colorCost = colorLines(player, lines, LoreEditType.APPEND_BOOK) + val outLines = ArrayList(lines.size) + val colorCost = colorLines(player, LoreEditType.APPEND_BOOK, + lines, outLines) - lore.addAll(lines) + lore.addAll(outLines) - meta.lore = lore + meta.setComponentLore(lore) result.itemMeta = meta if (result == first) return null // Handle xp xpCost.addAndGet(colorCost) // Cost of using color - xpCost.addAndGet(lines.size * LoreEditType.APPEND_BOOK.perLineCost) // per line cost + xpCost.addAndGet(outLines.size * LoreEditType.APPEND_BOOK.perLineCost) // per line cost xpCost.addAndGet(baseEditLoreXpCost(first, result, LoreEditType.APPEND_BOOK)) // Fixed cost and work penalty return result @@ -61,7 +66,7 @@ object AnvilLoreEditUtil { // remove lore val result = first.clone() val leftMeta = result.itemMeta ?: return null - val currentLore: ArrayList = DependencyManager.stripLore(result) + val currentLore = DependencyManager.stripLore(result) if (currentLore.isEmpty()) return null val uncolorCost = uncolorLines(player, currentLore, LoreEditType.REMOVE_BOOK) @@ -148,24 +153,23 @@ object AnvilLoreEditUtil { val result = first.clone() val meta = result.itemMeta ?: return null - val lore = if (meta.hasLore()) { - ArrayList(meta.lore!!) - } else ArrayList() + val lore = meta.componentLore() val appendEnd = LoreEditConfigUtil.paperLoreOrderIsEnd // A bit overdone to color 1 line but hey - val tempList = ArrayList(1) - tempList.add(second.itemMeta!!.displayName) - val colorCost = colorLines(player, tempList, LoreEditType.APPEND_PAPER) + val outList = ArrayList(1) + val colorCost = colorLines(player, LoreEditType.APPEND_PAPER, + Collections.singletonList(second.itemMeta!!.displayName), + outList) - val line = tempList[0] + val line = outList[0] if (appendEnd) lore.add(line) else lore.add(0, line) - meta.lore = lore + meta.setComponentLore(lore) result.itemMeta = meta if (result == first) return null @@ -185,7 +189,7 @@ object AnvilLoreEditUtil { val meta = result.itemMeta!! val removeEnd = LoreEditConfigUtil.paperLoreOrderIsEnd - val lore: ArrayList = DependencyManager.stripLore(result) + val lore = DependencyManager.stripLore(result) if (lore.isEmpty()) return null val line = if (removeEnd) lore.removeAt(lore.size - 1) @@ -197,18 +201,16 @@ object AnvilLoreEditUtil { // Update lore but make sure custom lore is put last DependencyManager.updateLore(result) - val finalLore = ArrayList() - finalLore.addAll(meta.lore ?: emptyList()) + val finalLore = ArrayList() + finalLore.addAll(meta.componentLore()) finalLore.addAll(lore) - meta.lore = finalLore + meta.setComponentLore(finalLore) result.itemMeta = meta if (result == first) return null // Get color cost to uncolor this line - val tempList = ArrayList(1) - tempList.add(line) - val uncolorCost = uncolorLines(player, tempList, LoreEditType.REMOVE_PAPER) + val uncolorCost = uncolorLine(player, line, LoreEditType.REMOVE_PAPER) // Handle other xp xpCost.addAndGet(uncolorCost) @@ -240,26 +242,37 @@ object AnvilLoreEditUtil { return xpCost } - private fun colorLines(player: Permissible, lines: ArrayList, editType: LoreEditType): Int { - val canUseHex = editType.allowHexColor - val canUseColorCode = editType.allowColorCode - val minimessage = editType.allowMinimessage + fun colorPermission(player: Permissible, editType: LoreEditType): AnvilColorUtil.ColorPermissions { + return AnvilColorUtil.calculatePermissions(player, + false, + editType.allowColorCode, + editType.allowHexColor, + editType.allowMinimessage, + AnvilColorUtil.ColorUseType.LORE_EDIT) + } + + private fun colorLine(line: String, permission: AnvilColorUtil.ColorPermissions): Component? { + return AnvilColorUtil.handleColor( + line, + permission + ) + } + + private fun colorLines(player: Permissible, editType: LoreEditType, + lines: List, outLines: MutableList): Int { + val permission = colorPermission(player, editType) val colorCost = editType.useColorCost // Handle color and minimessage of each lines var hasUsedColor = false - for ((index, line) in lines.withIndex()) { - val component = AnvilColorUtil.handleColor( - line, - player, - false, - canUseColorCode, canUseHex, minimessage, - AnvilColorUtil.ColorUseType.LORE_EDIT - ) + for (line in lines) { + val component = colorLine(line, permission) if (component != null) { hasUsedColor = true - lines[index] = MiniMessageUtil.legacy_mm.serialize(component) + outLines.add(component) + } else { + outLines.add(Component.text(line)) } } @@ -267,25 +280,31 @@ object AnvilLoreEditUtil { else 0 } - fun uncolorLines(player: Permissible, lines: ArrayList, editType: LoreEditType): Int { - if (!editType.shouldRemoveColorOnLoreRemoval) return 0 + fun uncolorLines(player: Permissible, lines: MutableList, editType: LoreEditType): Int { + val permission = colorPermission(player, editType) // Now handle color of each lines var hasUndidColor = false for ((index, line) in lines.withIndex()) { - val uncoloredLine = StringBuilder(line) + if(line == null){ + lines[index] = null + continue + } - val lineUndidColor = AnvilColorUtil.revertColor( - uncoloredLine, - player, - false, true, true, - AnvilColorUtil.ColorUseType.LORE_EDIT + val clearedLine = AnvilColorUtil.revertColorSmallest( + line, + permission ) - if (lineUndidColor) { + val result: String + if (clearedLine != null) { hasUndidColor = true - lines[index] = uncoloredLine.toString() + result = clearedLine + } else { + result = MiniMessageUtil.plain_text_mm.serialize(line) } + + lines[index] = MiniMessageUtil.plain_text_mm.deserialize(result) } return if (hasUndidColor) { @@ -295,4 +314,36 @@ object AnvilLoreEditUtil { } } + // do not output the uncolored line... + fun uncolorLine(player: Permissible, line: Component?, editType: LoreEditType): Int { + return uncolorLine(player, AtomicReference(line), editType) + } + + fun uncolorLine(player: Permissible, line: AtomicReference, editType: LoreEditType): Int { + val coloredComponent = line.get() ?: return 0 + val permission = colorPermission(player, editType) + + val clearedLine = AnvilColorUtil.revertColorSmallest( + coloredComponent, + permission + ) + + var hasUndidColor = false + val result: String + if(clearedLine != null){ + hasUndidColor = true + result = clearedLine + } else { + // Remove extra tags + result = MiniMessageUtil.plain_text_mm.serialize(coloredComponent) + } + line.set(MiniMessageUtil.plain_text_mm.deserialize(result)) + + return if (hasUndidColor) { + editType.removeColorCost + } else { + 0 + } + } + } \ No newline at end of file diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/MiniMessageUtil.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/MiniMessageUtil.kt index 10500e8..c33cb9c 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/MiniMessageUtil.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/util/MiniMessageUtil.kt @@ -1,18 +1,33 @@ package xyz.alexcrea.cuanvil.util +import net.kyori.adventure.text.TextComponent import net.kyori.adventure.text.minimessage.MiniMessage import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver import net.kyori.adventure.text.minimessage.tag.standard.StandardTags import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer +import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer +import xyz.alexcrea.cuanvil.dependency.util.PlatformUtil object MiniMessageUtil { - val mm = MiniMessage.builder() - .tags(TagResolver.resolver( - StandardTags.color(), - StandardTags.decorations())) + val color_only_mm = MiniMessage.builder() + .tags( + TagResolver.resolver( + StandardTags.color(), + StandardTags.decorations() + ) + ) .build() + val mm = if (PlatformUtil.isPaper) MiniMessage.miniMessage() + else color_only_mm + val legacy_mm = LegacyComponentSerializer.legacySection() + val plain_text_mm = PlainTextComponentSerializer.plainText() + + // Keeping track of this as most use of this can be replaced later on v2 with pure component alternative + fun fromLegacy(legacyText: String): TextComponent { + return legacy_mm.deserialize(legacyText) + } } diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/config/LoreEditConfigUtil.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/config/LoreEditConfigUtil.kt index 2a2fa3b..9d0eb6a 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/config/LoreEditConfigUtil.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/util/config/LoreEditConfigUtil.kt @@ -20,7 +20,6 @@ object LoreEditConfigUtil { const val ALLOW_MINIMESSAGE = "allow_minimessage" const val USE_COLOR_COST = "use_cost" - const val REMOVE_COLOR_ON_LORE_REMOVE = "remove_color_on_remove" const val REMOVE_COLOR_COST = "remove_color_cost" // Lore order config path @@ -46,7 +45,6 @@ object LoreEditConfigUtil { const val DEFAULT_ALLOW_MINIMESSAGE = true const val DEFAULT_USE_COLOR_COST = 0 - const val DEFAULT_REMOVE_COLOR_ON_LORE_REMOVE = false const val DEFAULT_REMOVE_COLOR_COST = 0 // Lore order config default diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/config/LoreEditType.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/config/LoreEditType.kt index bb1632e..8bd926a 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/config/LoreEditType.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/util/config/LoreEditType.kt @@ -8,11 +8,9 @@ import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil.DEFAULT_ALLOW_COLOR_C import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil.DEFAULT_ALLOW_HEX_COLOR import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil.DEFAULT_ALLOW_MINIMESSAGE import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil.DEFAULT_REMOVE_COLOR_COST -import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil.DEFAULT_REMOVE_COLOR_ON_LORE_REMOVE import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil.DEFAULT_USE_COLOR_COST import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil.REMOVE_COLOR_COST import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil.REMOVE_COLOR_COST_RANGE -import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil.REMOVE_COLOR_ON_LORE_REMOVE import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil.USE_COLOR_COST import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil.USE_COLOR_COST_RANGE import xyz.alexcrea.cuanvil.config.ConfigHolder.DEFAULT_CONFIG as CONFIG @@ -81,33 +79,30 @@ enum class LoreEditType( } /** - * Allow usage of color code on lore add + * Allow usage or removal of color code */ val allowColorCode: Boolean get() { - if (!isAppend) throw IllegalStateException("Can only call with an append edit type") return CONFIG .config .getBoolean("$rootPath.$ALLOW_COLOR_CODE", DEFAULT_ALLOW_COLOR_CODE) } /** - * Allow usage of hexadecimal color on lore add + * Allow usage or removal of hexadecimal color */ val allowHexColor: Boolean get() { - if (!isAppend) throw IllegalStateException("Can only call with an append edit type") return CONFIG .config .getBoolean("${rootPath}.$ALLOW_HEX_COLOR", DEFAULT_ALLOW_HEX_COLOR) } /** - * Allow usage of minimessage on lore add + * Allow usage or removal of minimessage on lore add */ val allowMinimessage: Boolean get() { - if (!isAppend) throw IllegalStateException("Can only call with an append edit type") return CONFIG .config .getBoolean("${rootPath}.$ALLOW_MINIMESSAGE", DEFAULT_ALLOW_MINIMESSAGE) @@ -127,17 +122,6 @@ enum class LoreEditType( } - /** - * Should the color code & hex color should get removed on lore remove - */ - val shouldRemoveColorOnLoreRemoval: Boolean - get() { - if (isAppend) throw IllegalStateException("Can only call with a remove edit type") - return CONFIG - .config - .getBoolean("${rootPath}.$REMOVE_COLOR_ON_LORE_REMOVE", DEFAULT_REMOVE_COLOR_ON_LORE_REMOVE) - } - /** * Cost when using either color code and hex color on lore remove */ diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 1c8c010..b645b55 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -60,6 +60,8 @@ sacrifice_illegal_enchant_cost: 1 # Color code are prefixed by "&" and hexadecimal color by "#". # Color code will not be applied if it colors nothing. "&&" can be used to write "&". # For minimessage search for minimessage formating https://docs.papermc.io/adventure/minimessage/format/ +# Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin +# but any global tag will be allowed later when v2 release allow_color_code: false allow_hexadecimal_color: false allow_minimessage: false @@ -304,6 +306,8 @@ lore_edit: # Color code are prefixed by "&" and hexadecimal color by "#" # Color code will not be applied if it colors nothing. "&&" can be used to write "&" # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ + # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin + # but any global tag will be allowed later when v2 release allow_color_code: true allow_hexadecimal_color: true allow_minimessage: true @@ -321,10 +325,21 @@ lore_edit: shared_additive: false # If removing the lore consume the book & quil do_consume: false - # If the color should get back to color code or hex format - remove_color_on_remove: true # Cost of replacing colors remove_color_cost: 0 + # Allowed some color and tags to be reverted to plain text + # Custom anvil will prioritise format that result is a smaller resulting text + # Note that not allowing certain format will lead to some lost of color or tags. + # If configuration are exact as append appending this book should result in the exact same color + # + # Color code will be prefixed by "&" and hexadecimal color by "#". + # If color code is allowed, "&" in the text will get converted to "&&" + # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ + # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin + # but any global tag will be allowed later when v2 release + allow_color_code: true + allow_hexadecimal_color: true + allow_minimessage: true paper: # Permission is ca.lore_edit.paper @@ -348,6 +363,8 @@ lore_edit: # Color code are prefixed by "&" and hexadecimal color by "#" # Color code will not be applied if it colors nothing. "&&" can be used to write "&" # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ + # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin + # but any global tag will be allowed later when v2 release allow_color_code: true allow_hexadecimal_color: true allow_minimessage: true @@ -364,10 +381,21 @@ lore_edit: shared_additive: false # If removing the lore line consume the paper do_consume: false - # If the color should get back to color code or hex format - remove_color_on_remove: true # Cost of replacing colors remove_color_cost: 0 + # Allowed some color and tags to be reverted to plain text + # Custom anvil will prioritise format that result is a smaller resulting text + # Note that not allowing certain format will lead to some lost of color or tags. + # If configuration are exact as append appending this paper should result in the exact same color + # + # Color code will be prefixed by "&" and hexadecimal color by "#". + # If color code is allowed, "&" in the text will get converted to "&&" + # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ + # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin + # but any global tag will be allowed later when v2 release + allow_color_code: true + allow_hexadecimal_color: true + allow_minimessage: true # Whether to show debug logging debug_log: false diff --git a/src/test/java/xyz/alexcrea/cuanvil/anvil/LoreEditTests.java b/src/test/java/xyz/alexcrea/cuanvil/anvil/LoreEditTests.java index ebfb84f..33b0f35 100644 --- a/src/test/java/xyz/alexcrea/cuanvil/anvil/LoreEditTests.java +++ b/src/test/java/xyz/alexcrea/cuanvil/anvil/LoreEditTests.java @@ -289,9 +289,9 @@ public class LoreEditTests extends SharedCustomAnvilTest { if (type.isAppend()) { ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.ALLOW_HEX_COLOR, true); ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.ALLOW_COLOR_CODE, true); + ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.ALLOW_MINIMESSAGE, true); ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.USE_COLOR_COST, 0); } else { - ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.REMOVE_COLOR_ON_LORE_REMOVE, false); ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.REMOVE_COLOR_COST, 0); } @@ -437,7 +437,6 @@ public class LoreEditTests extends SharedCustomAnvilTest { public void testColorCost(LoreEditType type) { ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.USE_COLOR_COST, COLOR_USE_COST); ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.REMOVE_COLOR_COST, COLOR_REMOVE_COST); - ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.REMOVE_COLOR_ON_LORE_REMOVE, true); TestDataContainer singleLData = singleLineTypeToTest.get(type); TestDataContainer multiLData = multiLineTypeToTest.get(type); @@ -481,8 +480,6 @@ public class LoreEditTests extends SharedCustomAnvilTest { @ParameterizedTest @MethodSource("onlyRemoveTypes") public void testColorRemoveEnabled(LoreEditType type) { - ConfigHolder.DEFAULT_CONFIG.getConfig().set(type.getRootPath() + "." + LoreEditConfigUtil.REMOVE_COLOR_ON_LORE_REMOVE, true); - TestDataContainer singleLData = singleLineTypeToTest.get(type); TestDataContainer multiLData = multiLineTypeToTest.get(type); From 517fcf3430f2ce07018bfa789615ec0aa5a91338 Mon Sep 17 00:00:00 2001 From: alexcrea Date: Thu, 23 Oct 2025 15:34:04 +0200 Subject: [PATCH 6/8] disallow use of hex code and minimessage on append --- defaultconfigs/1.18/config.yml | 12 ++++-- defaultconfigs/1.21.9/config.yml | 12 ++++-- defaultconfigs/1.21/config.yml | 12 ++++-- .../cuanvil/listener/AnvilResultListener.kt | 5 ++- .../cuanvil/listener/PrepareAnvilListener.kt | 2 +- .../alexcrea/cuanvil/util/AnvilColorUtil.kt | 43 +++++++------------ .../cuanvil/util/AnvilLoreEditUtil.kt | 11 ++--- src/main/resources/config.yml | 12 ++++-- 8 files changed, 58 insertions(+), 51 deletions(-) diff --git a/defaultconfigs/1.18/config.yml b/defaultconfigs/1.18/config.yml index 692ee2d..2caafe3 100644 --- a/defaultconfigs/1.18/config.yml +++ b/defaultconfigs/1.18/config.yml @@ -306,8 +306,10 @@ lore_edit: # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin # but any global tag will be allowed later when v2 release + # + # Note that currently minimessage would disable hex code when adding color allow_color_code: true - allow_hexadecimal_color: true + allow_hexadecimal_color: false allow_minimessage: true remove: @@ -336,7 +338,7 @@ lore_edit: # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin # but any global tag will be allowed later when v2 release allow_color_code: true - allow_hexadecimal_color: true + allow_hexadecimal_color: false allow_minimessage: true paper: @@ -363,8 +365,10 @@ lore_edit: # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin # but any global tag will be allowed later when v2 release + # + # Note that currently minimessage would disable hex code when adding color allow_color_code: true - allow_hexadecimal_color: true + allow_hexadecimal_color: false allow_minimessage: true color_use_cost: 0 @@ -392,7 +396,7 @@ lore_edit: # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin # but any global tag will be allowed later when v2 release allow_color_code: true - allow_hexadecimal_color: true + allow_hexadecimal_color: false allow_minimessage: true # Whether to show debug logging diff --git a/defaultconfigs/1.21.9/config.yml b/defaultconfigs/1.21.9/config.yml index 028c401..2602e56 100644 --- a/defaultconfigs/1.21.9/config.yml +++ b/defaultconfigs/1.21.9/config.yml @@ -318,8 +318,10 @@ lore_edit: # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin # but any global tag will be allowed later when v2 release + # + # Note that currently minimessage would disable hex code when adding color allow_color_code: true - allow_hexadecimal_color: true + allow_hexadecimal_color: false allow_minimessage: true remove: @@ -348,7 +350,7 @@ lore_edit: # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin # but any global tag will be allowed later when v2 release allow_color_code: true - allow_hexadecimal_color: true + allow_hexadecimal_color: false allow_minimessage: true paper: @@ -375,8 +377,10 @@ lore_edit: # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin # but any global tag will be allowed later when v2 release + # + # Note that currently minimessage would disable hex code when adding color allow_color_code: true - allow_hexadecimal_color: true + allow_hexadecimal_color: false allow_minimessage: true color_use_cost: 0 @@ -404,7 +408,7 @@ lore_edit: # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin # but any global tag will be allowed later when v2 release allow_color_code: true - allow_hexadecimal_color: true + allow_hexadecimal_color: false allow_minimessage: true # Whether to show debug logging diff --git a/defaultconfigs/1.21/config.yml b/defaultconfigs/1.21/config.yml index fe655c2..139148b 100644 --- a/defaultconfigs/1.21/config.yml +++ b/defaultconfigs/1.21/config.yml @@ -306,8 +306,10 @@ lore_edit: # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin # but any global tag will be allowed later when v2 release + # + # Note that currently minimessage would disable hex code when adding color allow_color_code: true - allow_hexadecimal_color: true + allow_hexadecimal_color: false allow_minimessage: true remove: @@ -336,7 +338,7 @@ lore_edit: # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin # but any global tag will be allowed later when v2 release allow_color_code: true - allow_hexadecimal_color: true + allow_hexadecimal_color: false allow_minimessage: true paper: @@ -363,8 +365,10 @@ lore_edit: # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin # but any global tag will be allowed later when v2 release + # + # Note that currently minimessage would disable hex code when adding color allow_color_code: true - allow_hexadecimal_color: true + allow_hexadecimal_color: false allow_minimessage: true color_use_cost: 0 @@ -392,7 +396,7 @@ lore_edit: # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin # but any global tag will be allowed later when v2 release allow_color_code: true - allow_hexadecimal_color: true + allow_hexadecimal_color: false allow_minimessage: true # Whether to show debug logging diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/listener/AnvilResultListener.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/listener/AnvilResultListener.kt index db2dfb0..bc3afa4 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/listener/AnvilResultListener.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/listener/AnvilResultListener.kt @@ -26,6 +26,7 @@ import xyz.alexcrea.cuanvil.util.AnvilLoreEditUtil import xyz.alexcrea.cuanvil.util.AnvilUseType import xyz.alexcrea.cuanvil.util.AnvilXpUtil import xyz.alexcrea.cuanvil.util.CustomRecipeUtil +import xyz.alexcrea.cuanvil.util.MiniMessageUtil import xyz.alexcrea.cuanvil.util.UnitRepairUtil.getRepair import xyz.alexcrea.cuanvil.util.config.LoreEditConfigUtil import xyz.alexcrea.cuanvil.util.config.LoreEditType @@ -412,7 +413,9 @@ class AnvilResultListener : Listener { val bookPage = StringBuilder() lore.forEach { if (bookPage.isNotEmpty()) bookPage.append('\n') - bookPage.append(it) + if(it == null) return@forEach + + bookPage.append(MiniMessageUtil.plain_text_mm.serialize(it)) } val resultPage = bookPage.toString() diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/listener/PrepareAnvilListener.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/listener/PrepareAnvilListener.kt index 17d5d0d..f491862 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/listener/PrepareAnvilListener.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/listener/PrepareAnvilListener.kt @@ -195,7 +195,7 @@ class PrepareAnvilListener : Listener { renameText, player, ConfigOptions.permissionNeededForColor, ConfigOptions.allowColorCode, ConfigOptions.allowHexadecimalColor, ConfigOptions.allowMinimessage, - AnvilColorUtil.ColorUseType.RENAME + AnvilColorUtil.ColorUseType.RENAME, true ) if (component != null) { diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilColorUtil.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilColorUtil.kt index 0abcaaf..320eef1 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilColorUtil.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilColorUtil.kt @@ -29,7 +29,9 @@ object AnvilColorUtil { allowColorCode: Boolean, allowHexadecimalColor: Boolean, allowMinimessage: Boolean, - useType: ColorUseType): ColorPermissions { + useType: ColorUseType, + isAppend: Boolean = true + ): ColorPermissions { if (!allowColorCode && !allowHexadecimalColor && !allowMinimessage) return ColorPermissions( canUseColorCode = false, @@ -41,15 +43,20 @@ object AnvilColorUtil { allowColorCode && (!usePermission || useType.colorCodePerm == null || player.hasPermission( useType.colorCodePerm )) - val canUseHexColor = - allowHexadecimalColor && (!usePermission || useType.hexColorPerm == null || player.hasPermission( - useType.hexColorPerm - )) + val canUseMinimessage = allowMinimessage && (!usePermission || useType.minimessagePerm == null || player.hasPermission( useType.minimessagePerm )) + // Do not allow minimessage and hex color at the same time when coming from string to component (usually/assumed append) + val minimessageConflict = canUseMinimessage && isAppend + + val canUseHexColor = !minimessageConflict && + allowHexadecimalColor && (!usePermission || useType.hexColorPerm == null || player.hasPermission( + useType.hexColorPerm + )) + return ColorPermissions(canUseColorCode, canUseHexColor, canUseMinimessage) } @@ -64,11 +71,12 @@ object AnvilColorUtil { allowColorCode: Boolean, allowHexadecimalColor: Boolean, allowMinimessage: Boolean, - useType: ColorUseType + useType: ColorUseType, + isAppend: Boolean ): Component? { val permission = calculatePermissions(player, usePermission, allowColorCode, allowHexadecimalColor, allowMinimessage, - useType) + useType, isAppend) return handleColor(textToColorText, permission) } @@ -117,27 +125,6 @@ object AnvilColorUtil { else null } - /** - * Best effort to revert a component to the smallest allowed string - * that would result in it getting closest as possible to handleColor - * with current set of color type, color use type and player permissions - * @return the new component if had any change. null otherwise - */ - fun revertColorSmallest( - component: Component, - player: Permissible, - usePermission: Boolean, - allowColorCode: Boolean, - allowMinimessage: Boolean, - allowHexadecimalColor: Boolean, - useType: ColorUseType - ): String? { - val permission = calculatePermissions(player, usePermission, - allowColorCode, allowHexadecimalColor, allowMinimessage, - useType) - return revertColorSmallest(component, permission) - } - /** * Best effort to revert a component to the smallest allowed string * that would result in it getting closest as possible to handleColor diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilLoreEditUtil.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilLoreEditUtil.kt index 4135df7..943be5f 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilLoreEditUtil.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilLoreEditUtil.kt @@ -117,10 +117,10 @@ object AnvilLoreEditUtil { } fun tryLoreEditByBook(player: HumanEntity, first: ItemStack, second: ItemStack, xpCost: AtomicInteger): ItemStack? { - val bookType = bookLoreEditIsAppend(first, second) ?: return null + val isAppend = bookLoreEditIsAppend(first, second) ?: return null val meta = second.itemMeta as BookMeta - return if (bookType) handleLoreAppendByBook(player, first, meta, xpCost) + return if (isAppend) handleLoreAppendByBook(player, first, meta, xpCost) else handleLoreRemoveByBook(player, first, xpCost) } @@ -225,9 +225,9 @@ object AnvilLoreEditUtil { second: ItemStack, xpCost: AtomicInteger ): ItemStack? { - val bookType = paperLoreEditIsAppend(first, second) ?: return null + val isAppend = paperLoreEditIsAppend(first, second) ?: return null - return if (bookType) handleLoreAppendByPaper(player, first, second, xpCost) + return if (isAppend) handleLoreAppendByPaper(player, first, second, xpCost) else handleLoreRemoveByPaper(player, first, xpCost) } @@ -248,7 +248,8 @@ object AnvilLoreEditUtil { editType.allowColorCode, editType.allowHexColor, editType.allowMinimessage, - AnvilColorUtil.ColorUseType.LORE_EDIT) + AnvilColorUtil.ColorUseType.LORE_EDIT, + editType.isAppend) } private fun colorLine(line: String, permission: AnvilColorUtil.ColorPermissions): Component? { diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index b645b55..79c4278 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -308,8 +308,10 @@ lore_edit: # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin # but any global tag will be allowed later when v2 release + # + # Note that currently minimessage would disable hex code when adding color allow_color_code: true - allow_hexadecimal_color: true + allow_hexadecimal_color: false allow_minimessage: true remove: @@ -338,7 +340,7 @@ lore_edit: # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin # but any global tag will be allowed later when v2 release allow_color_code: true - allow_hexadecimal_color: true + allow_hexadecimal_color: false allow_minimessage: true paper: @@ -365,8 +367,10 @@ lore_edit: # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin # but any global tag will be allowed later when v2 release + # + # Note that currently minimessage would disable hex code when adding color allow_color_code: true - allow_hexadecimal_color: true + allow_hexadecimal_color: false allow_minimessage: true color_use_cost: 0 @@ -394,7 +398,7 @@ lore_edit: # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin # but any global tag will be allowed later when v2 release allow_color_code: true - allow_hexadecimal_color: true + allow_hexadecimal_color: false allow_minimessage: true # Whether to show debug logging From b9aae9e79901a3eb5e1a388021c6203e52921a82 Mon Sep 17 00:00:00 2001 From: alexcrea Date: Thu, 23 Oct 2025 15:48:05 +0200 Subject: [PATCH 7/8] update doc --- defaultconfigs/1.18/config.yml | 8 -------- defaultconfigs/1.21.9/config.yml | 8 -------- defaultconfigs/1.21/config.yml | 8 -------- src/main/resources/config.yml | 8 -------- 4 files changed, 32 deletions(-) diff --git a/defaultconfigs/1.18/config.yml b/defaultconfigs/1.18/config.yml index 2caafe3..877cee9 100644 --- a/defaultconfigs/1.18/config.yml +++ b/defaultconfigs/1.18/config.yml @@ -304,8 +304,6 @@ lore_edit: # Color code are prefixed by "&" and hexadecimal color by "#" # Color code will not be applied if it colors nothing. "&&" can be used to write "&" # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ - # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin - # but any global tag will be allowed later when v2 release # # Note that currently minimessage would disable hex code when adding color allow_color_code: true @@ -335,8 +333,6 @@ lore_edit: # Color code will be prefixed by "&" and hexadecimal color by "#". # If color code is allowed, "&" in the text will get converted to "&&" # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ - # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin - # but any global tag will be allowed later when v2 release allow_color_code: true allow_hexadecimal_color: false allow_minimessage: true @@ -363,8 +359,6 @@ lore_edit: # Color code are prefixed by "&" and hexadecimal color by "#" # Color code will not be applied if it colors nothing. "&&" can be used to write "&" # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ - # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin - # but any global tag will be allowed later when v2 release # # Note that currently minimessage would disable hex code when adding color allow_color_code: true @@ -393,8 +387,6 @@ lore_edit: # Color code will be prefixed by "&" and hexadecimal color by "#". # If color code is allowed, "&" in the text will get converted to "&&" # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ - # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin - # but any global tag will be allowed later when v2 release allow_color_code: true allow_hexadecimal_color: false allow_minimessage: true diff --git a/defaultconfigs/1.21.9/config.yml b/defaultconfigs/1.21.9/config.yml index 2602e56..cf9460e 100644 --- a/defaultconfigs/1.21.9/config.yml +++ b/defaultconfigs/1.21.9/config.yml @@ -316,8 +316,6 @@ lore_edit: # Color code are prefixed by "&" and hexadecimal color by "#" # Color code will not be applied if it colors nothing. "&&" can be used to write "&" # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ - # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin - # but any global tag will be allowed later when v2 release # # Note that currently minimessage would disable hex code when adding color allow_color_code: true @@ -347,8 +345,6 @@ lore_edit: # Color code will be prefixed by "&" and hexadecimal color by "#". # If color code is allowed, "&" in the text will get converted to "&&" # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ - # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin - # but any global tag will be allowed later when v2 release allow_color_code: true allow_hexadecimal_color: false allow_minimessage: true @@ -375,8 +371,6 @@ lore_edit: # Color code are prefixed by "&" and hexadecimal color by "#" # Color code will not be applied if it colors nothing. "&&" can be used to write "&" # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ - # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin - # but any global tag will be allowed later when v2 release # # Note that currently minimessage would disable hex code when adding color allow_color_code: true @@ -405,8 +399,6 @@ lore_edit: # Color code will be prefixed by "&" and hexadecimal color by "#". # If color code is allowed, "&" in the text will get converted to "&&" # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ - # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin - # but any global tag will be allowed later when v2 release allow_color_code: true allow_hexadecimal_color: false allow_minimessage: true diff --git a/defaultconfigs/1.21/config.yml b/defaultconfigs/1.21/config.yml index 139148b..d7807e9 100644 --- a/defaultconfigs/1.21/config.yml +++ b/defaultconfigs/1.21/config.yml @@ -304,8 +304,6 @@ lore_edit: # Color code are prefixed by "&" and hexadecimal color by "#" # Color code will not be applied if it colors nothing. "&&" can be used to write "&" # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ - # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin - # but any global tag will be allowed later when v2 release # # Note that currently minimessage would disable hex code when adding color allow_color_code: true @@ -335,8 +333,6 @@ lore_edit: # Color code will be prefixed by "&" and hexadecimal color by "#". # If color code is allowed, "&" in the text will get converted to "&&" # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ - # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin - # but any global tag will be allowed later when v2 release allow_color_code: true allow_hexadecimal_color: false allow_minimessage: true @@ -363,8 +359,6 @@ lore_edit: # Color code are prefixed by "&" and hexadecimal color by "#" # Color code will not be applied if it colors nothing. "&&" can be used to write "&" # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ - # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin - # but any global tag will be allowed later when v2 release # # Note that currently minimessage would disable hex code when adding color allow_color_code: true @@ -393,8 +387,6 @@ lore_edit: # Color code will be prefixed by "&" and hexadecimal color by "#". # If color code is allowed, "&" in the text will get converted to "&&" # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ - # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin - # but any global tag will be allowed later when v2 release allow_color_code: true allow_hexadecimal_color: false allow_minimessage: true diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 79c4278..5476ec7 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -306,8 +306,6 @@ lore_edit: # Color code are prefixed by "&" and hexadecimal color by "#" # Color code will not be applied if it colors nothing. "&&" can be used to write "&" # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ - # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin - # but any global tag will be allowed later when v2 release # # Note that currently minimessage would disable hex code when adding color allow_color_code: true @@ -337,8 +335,6 @@ lore_edit: # Color code will be prefixed by "&" and hexadecimal color by "#". # If color code is allowed, "&" in the text will get converted to "&&" # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ - # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin - # but any global tag will be allowed later when v2 release allow_color_code: true allow_hexadecimal_color: false allow_minimessage: true @@ -365,8 +361,6 @@ lore_edit: # Color code are prefixed by "&" and hexadecimal color by "#" # Color code will not be applied if it colors nothing. "&&" can be used to write "&" # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ - # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin - # but any global tag will be allowed later when v2 release # # Note that currently minimessage would disable hex code when adding color allow_color_code: true @@ -395,8 +389,6 @@ lore_edit: # Color code will be prefixed by "&" and hexadecimal color by "#". # If color code is allowed, "&" in the text will get converted to "&&" # For minimessage see minimessage formating https://docs.papermc.io/adventure/minimessage/format/ - # Note that only color and decoration tags are allowed for minimisage in the v1 version of this plugin - # but any global tag will be allowed later when v2 release allow_color_code: true allow_hexadecimal_color: false allow_minimessage: true From e9a2890cfb0bb25a0c0dd714497c6e60fad59372 Mon Sep 17 00:00:00 2001 From: alexcrea Date: Mon, 27 Oct 2025 16:48:09 +0100 Subject: [PATCH 8/8] tag detection --- .../cuanvil/listener/PrepareAnvilListener.kt | 2 +- .../alexcrea/cuanvil/util/AnvilColorUtil.kt | 60 ++++++++++++++----- .../cuanvil/util/AnvilLoreEditUtil.kt | 3 +- 3 files changed, 46 insertions(+), 19 deletions(-) diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/listener/PrepareAnvilListener.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/listener/PrepareAnvilListener.kt index f491862..17d5d0d 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/listener/PrepareAnvilListener.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/listener/PrepareAnvilListener.kt @@ -195,7 +195,7 @@ class PrepareAnvilListener : Listener { renameText, player, ConfigOptions.permissionNeededForColor, ConfigOptions.allowColorCode, ConfigOptions.allowHexadecimalColor, ConfigOptions.allowMinimessage, - AnvilColorUtil.ColorUseType.RENAME, true + AnvilColorUtil.ColorUseType.RENAME ) if (component != null) { diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilColorUtil.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilColorUtil.kt index 320eef1..35ed486 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilColorUtil.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilColorUtil.kt @@ -4,6 +4,7 @@ import net.kyori.adventure.text.Component import org.bukkit.permissions.Permissible import java.util.regex.Matcher import java.util.regex.Pattern +import kotlin.text.indexOf object AnvilColorUtil { private val HEX_PATTERN: Pattern = Pattern.compile("#[A-Fa-f0-9]{6}") // pattern to find hexadecimal string @@ -29,8 +30,7 @@ object AnvilColorUtil { allowColorCode: Boolean, allowHexadecimalColor: Boolean, allowMinimessage: Boolean, - useType: ColorUseType, - isAppend: Boolean = true + useType: ColorUseType ): ColorPermissions { if (!allowColorCode && !allowHexadecimalColor && !allowMinimessage) return ColorPermissions( @@ -49,10 +49,7 @@ object AnvilColorUtil { useType.minimessagePerm )) - // Do not allow minimessage and hex color at the same time when coming from string to component (usually/assumed append) - val minimessageConflict = canUseMinimessage && isAppend - - val canUseHexColor = !minimessageConflict && + val canUseHexColor = allowHexadecimalColor && (!usePermission || useType.hexColorPerm == null || player.hasPermission( useType.hexColorPerm )) @@ -71,12 +68,11 @@ object AnvilColorUtil { allowColorCode: Boolean, allowHexadecimalColor: Boolean, allowMinimessage: Boolean, - useType: ColorUseType, - isAppend: Boolean + useType: ColorUseType ): Component? { val permission = calculatePermissions(player, usePermission, allowColorCode, allowHexadecimalColor, allowMinimessage, - useType, isAppend) + useType) return handleColor(textToColorText, permission) } @@ -101,7 +97,7 @@ object AnvilColorUtil { } if (permission.canUseHexColor) { - val nbReplacement = replaceHexToColor(textToColor, 7) + val nbReplacement = replaceHexToColor(textToColor, 7, permission.canUseMinimessage) if (nbReplacement > 0) useColor = true } @@ -109,13 +105,13 @@ object AnvilColorUtil { val previousStr = textToColor.toString() var result: Component = MiniMessageUtil.legacy_mm.deserialize(previousStr) if(permission.canUseMinimessage) { - // we dance with formats here TODO maybe extract, if possible, only the "text" part and use it for compare with previous as tag would be missing? + // we dance with formats here val toMinimessage = MiniMessageUtil.mm.serialize(result) val hackySolution = toMinimessage.replace("\\<", "<") val fromMinimessage = MiniMessageUtil.mm.deserialize(hackySolution) - val toLegacy = MiniMessageUtil.legacy_mm.serialize(fromMinimessage) + val asPlain = MiniMessageUtil.plain_text_mm.serialize(fromMinimessage) - if(previousStr != toLegacy){ + if(previousStr != asPlain){ useColor = true result = fromMinimessage } @@ -162,8 +158,10 @@ object AnvilColorUtil { // In case we still has some § around by lack of permission we need to convert it back from legacy // In other word it's time for dance #3 val fromLegacy = MiniMessageUtil.legacy_mm.deserialize(legacyMessage.toString()) - val middleGround = MiniMessageUtil.color_only_mm.serialize(fromLegacy) - val hackySolution = middleGround.replace("\\<", "<") + val middleGround = MiniMessageUtil.mm.serialize(fromLegacy) + val hackySolutionStb = StringBuilder(middleGround) + replaceAll(hackySolutionStb, "\\<", "<", 2) + val hackySolution = hackySolutionStb.toString() val result: String = if(permission.canUseMinimessage) hackySolution @@ -202,7 +200,7 @@ object AnvilColorUtil { * @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 { + private fun replaceHexToColor(builder: StringBuilder, endOffset: Int, checkTag: Boolean): Int { val matcher: Matcher = HEX_PATTERN.matcher(builder) var numberOfChanges = 0 @@ -211,6 +209,10 @@ 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)) { + startIndex += 1 // Avoid infinite loop + continue + } builder.replace(startIndex, startIndex + 1, "§x") startIndex += 2 @@ -225,6 +227,32 @@ object AnvilColorUtil { return numberOfChanges } + // Simple check if < > with some smart check like <> > not taken into account + // This is easily bypassable but if the player want to bypass he has better alternative + // AKA should avoid getting into any tag + private fun isInTag(builder: StringBuilder, index: Int): Boolean { + // Check left tag we have < after last > + val left = builder.slice(0..index) + val leftIndex = left.lastIndexOf("<") + var rightIndex = left.lastIndexOf(">") + + // last < do not exist or is before last > + if(leftIndex == -1 || rightIndex > leftIndex) return false + + val right = builder.slice(index..") + + // first > do not exist or is after first < (if exist) + if (rightIndex == -1 || (newleftIndex != -1 && newleftIndex < rightIndex)) return false + + // Then finally we use minimessage to check for tag + val expectedTag = builder.substring(leftIndex, newleftIndex + 1) + val notag = MiniMessageUtil.mm.stripTags(expectedTag) + + return notag != expectedTag + } + /** * Replace every hex color from the minecraft format to a format like #000000 * @param builder The builder to replace the minecraft hex color from. diff --git a/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilLoreEditUtil.kt b/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilLoreEditUtil.kt index 943be5f..36f0efb 100644 --- a/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilLoreEditUtil.kt +++ b/src/main/kotlin/xyz/alexcrea/cuanvil/util/AnvilLoreEditUtil.kt @@ -248,8 +248,7 @@ object AnvilLoreEditUtil { editType.allowColorCode, editType.allowHexColor, editType.allowMinimessage, - AnvilColorUtil.ColorUseType.LORE_EDIT, - editType.isAppend) + AnvilColorUtil.ColorUseType.LORE_EDIT) } private fun colorLine(line: String, permission: AnvilColorUtil.ColorPermissions): Component? {