add minimessage for color and decoration only (#92)

no test so I don't like it but can't really work more on it currently
This commit is contained in:
alexcrea 2025-11-06 10:46:09 +01:00 committed by GitHub
commit 0b1e3bc12c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
22 changed files with 652 additions and 224 deletions

View file

@ -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:
@ -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.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)

View file

@ -18,7 +18,7 @@ plugins {
}
group = "xyz.alexcrea"
version = "1.15.1"
version = "1.15.2"
val effectiveVersion = "$version" +
(if (System.getenv("SMALL_COMMIT_HASH") != null) "-dev-${System.getenv("SMALL_COMMIT_HASH")!!}" else "")
@ -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)

View file

@ -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 see 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.
#
@ -301,9 +303,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/
#
# Note that currently minimessage would disable hex code when adding color
allow_color_code: true
allow_hexadecimal_color: true
use_cost: 0
allow_hexadecimal_color: false
allow_minimessage: true
remove:
# If removing lore using book & quil is enabled
@ -318,10 +323,19 @@ 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/
allow_color_code: true
allow_hexadecimal_color: false
allow_minimessage: true
paper:
# Permission is ca.lore_edit.paper
@ -344,10 +358,13 @@ 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 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
use_cost: 0
remove_line:
# If removing lore line using paper is enabled
@ -360,10 +377,19 @@ 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/
allow_color_code: true
allow_hexadecimal_color: false
allow_minimessage: true
# Whether to show debug logging
debug_log: false

View file

@ -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.
#
@ -313,9 +315,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/
#
# Note that currently minimessage would disable hex code when adding color
allow_color_code: true
allow_hexadecimal_color: true
use_cost: 0
allow_hexadecimal_color: false
allow_minimessage: true
remove:
# If removing lore using book & quil is enabled
@ -330,10 +335,19 @@ 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/
allow_color_code: true
allow_hexadecimal_color: false
allow_minimessage: true
paper:
# Permission is ca.lore_edit.paper
@ -356,10 +370,13 @@ 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 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
use_cost: 0
remove_line:
# If removing lore line using paper is enabled
@ -372,10 +389,19 @@ 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/
allow_color_code: true
allow_hexadecimal_color: false
allow_minimessage: true
# Whether to show debug logging
debug_log: false

View file

@ -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.
#
@ -301,9 +303,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/
#
# Note that currently minimessage would disable hex code when adding color
allow_color_code: true
allow_hexadecimal_color: true
use_cost: 0
allow_hexadecimal_color: false
allow_minimessage: true
remove:
# If removing lore using book & quil is enabled
@ -318,10 +323,19 @@ 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/
allow_color_code: true
allow_hexadecimal_color: false
allow_minimessage: true
paper:
# Permission is ca.lore_edit.paper
@ -344,10 +358,13 @@ 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 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
use_cost: 0
remove_line:
# If removing lore line using paper is enabled
@ -360,10 +377,19 @@ 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/
allow_color_code: true
allow_hexadecimal_color: false
allow_minimessage: true
# Whether to show debug logging
debug_log: false

View file

@ -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")
}
repositories {
maven("https://repo.papermc.io/repository/maven-public/")
}
// Set target version
tasks.withType<JavaCompile>().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)
}
}

View file

@ -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<Component> {
val lore: List<Component>?
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<Component?>) {
if(isPaper){
this.lore(lore)
} else {
val legacyLore = ArrayList<String?>(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)
}
}
}

View file

@ -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 {

View file

@ -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);
}
}

View file

@ -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 || allowMinimessage
}
/**

View file

@ -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("")

View file

@ -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<String> {
val lore = ArrayList<String>()
fun stripLore(item: ItemStack): MutableList<Component?> {
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<Component?>()
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
}
}
}

View file

@ -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
@ -25,11 +26,13 @@ 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
import java.util.*
import java.util.concurrent.atomic.AtomicInteger
import java.util.concurrent.atomic.AtomicReference
import kotlin.math.min
class AnvilResultListener : Listener {
@ -397,8 +400,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
@ -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()
@ -443,10 +446,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 +459,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 +492,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<String>(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
}

View file

@ -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.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.

View file

@ -1,97 +1,174 @@
package xyz.alexcrea.cuanvil.util
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
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
*/
fun handleColor(
textToColor: StringBuilder,
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
): Boolean {
if (!allowColorCode && !allowHexadecimalColor) return false
): ColorPermissions {
if (!allowColorCode && !allowHexadecimalColor && !allowMinimessage)
return ColorPermissions(
canUseColorCode = false,
canUseHexColor = false,
canUseMinimessage = false
)
val canUseColorCode =
allowColorCode && (!usePermission || useType.colorCodePerm == null || player.hasPermission(
useType.colorCodePerm
))
val canUseMinimessage =
allowMinimessage && (!usePermission || useType.minimessagePerm == null || player.hasPermission(
useType.minimessagePerm
))
val canUseHexColor =
allowHexadecimalColor && (!usePermission || useType.hexColorPerm == null || player.hasPermission(
useType.hexColorPerm
))
if ((!canUseColorCode) && (!canUseHexColor)) return false
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) {
if (permission.canUseColorCode) { // maybe should use LegacyComponentSerializer ?
var nbReplacement = replaceAll(textToColor, "&", "§", 2)
nbReplacement -= 2 * replaceAll(textToColor, "§§", "&", 2)
if (nbReplacement > 0) useColor = true
}
if (canUseHexColor) {
val nbReplacement = replaceHexToColor(textToColor, 7)
if (permission.canUseHexColor) {
val nbReplacement = replaceHexToColor(textToColor, 7, permission.canUseMinimessage)
if (nbReplacement > 0) useColor = true
}
return useColor
val previousStr = textToColor.toString()
var result: Component = MiniMessageUtil.legacy_mm.deserialize(previousStr)
if(permission.canUseMinimessage) {
// we dance with formats here
val toMinimessage = MiniMessageUtil.mm.serialize(result)
val hackySolution = toMinimessage.replace("\\<", "<")
val fromMinimessage = MiniMessageUtil.mm.deserialize(hackySolution)
val asPlain = MiniMessageUtil.plain_text_mm.serialize(fromMinimessage)
if(previousStr != asPlain){
useColor = true
result = fromMinimessage
}
}
return if(useColor) result
else null
}
/**
* 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 permitted use
* @return a new component if had any change. null otherwise
*/
fun revertColor(
colorToText: StringBuilder,
player: Permissible,
usePermission: Boolean,
allowColorCode: Boolean,
allowHexadecimalColor: Boolean,
useType: ColorUseType
): Boolean {
if (!allowColorCode && !allowHexadecimalColor) return false
fun revertColorSmallest(
component: Component?,
permission: ColorPermissions
): String? {
if(!permission.allowed() || component == null) return null
val canUseColorCode =
allowColorCode && (!usePermission || useType.colorCodePerm == null || player.hasPermission(
useType.colorCodePerm
))
val canUseHexColor =
allowHexadecimalColor && (!usePermission || useType.hexColorPerm == null || player.hasPermission(
useType.hexColorPerm
))
val transformed = MiniMessageUtil.mm.serialize(component)
val plainTransform = MiniMessageUtil.plain_text_mm.serialize(component)
if(transformed == plainTransform) return null
if(permission.onlyMinimessage()){
return transformed
}
if ((!canUseColorCode) && (!canUseHexColor)) return false
var hasReversed = false
// 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.mm.serialize(fromLegacy)
val hackySolutionStb = StringBuilder(middleGround)
replaceAll(hackySolutionStb, "\\<", "<", 2)
val hackySolution = hackySolutionStb.toString()
val result: String =
if(permission.canUseMinimessage) hackySolution
else MiniMessageUtil.mm.stripTags(hackySolution)
return if(result == plainTransform) null
else result
}
/**
@ -123,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
@ -132,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
@ -146,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..<builder.length)
val newleftIndex = right.indexOf("<")
rightIndex = right.indexOf(">")
// 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.
@ -177,10 +284,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.rename.minimessage"),
LORE_EDIT(null, null, null)
}
}

View file

@ -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<String>(meta.lore!!)
} else ArrayList()
val lore = meta.componentLore()
val page = book.pages[0]
val lines = ArrayList<String>(page.split("\n"))
val colorCost = colorLines(player, lines, LoreEditType.APPEND_BOOK)
val outLines = ArrayList<Component>(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<String> = DependencyManager.stripLore(result)
val currentLore = DependencyManager.stripLore(result)
if (currentLore.isEmpty()) return null
val uncolorCost = uncolorLines(player, currentLore, LoreEditType.REMOVE_BOOK)
@ -112,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)
}
@ -148,24 +153,23 @@ object AnvilLoreEditUtil {
val result = first.clone()
val meta = result.itemMeta ?: return null
val lore = if (meta.hasLore()) {
ArrayList<String>(meta.lore!!)
} else ArrayList()
val lore = meta.componentLore()
val appendEnd = LoreEditConfigUtil.paperLoreOrderIsEnd
// A bit overdone to color 1 line but hey
val tempList = ArrayList<String>(1)
tempList.add(second.itemMeta!!.displayName)
val colorCost = colorLines(player, tempList, LoreEditType.APPEND_PAPER)
val outList = ArrayList<Component>(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<String> = 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<String>()
finalLore.addAll(meta.lore ?: emptyList())
val finalLore = ArrayList<Component?>()
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<String>(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)
@ -223,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)
}
@ -240,55 +242,69 @@ object AnvilLoreEditUtil {
return xpCost
}
private fun colorLines(player: Permissible, lines: ArrayList<String>, editType: LoreEditType): Int {
val canUseHex = editType.allowHexColor
val canUseColorCode = editType.allowColorCode
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<String>, outLines: MutableList<Component>): Int {
val permission = colorPermission(player, editType)
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)
for (line in lines) {
val component = colorLine(line, permission)
val lineUsedColor = AnvilColorUtil.handleColor(
coloredLine,
player,
false, canUseColorCode, canUseHex,
AnvilColorUtil.ColorUseType.LORE_EDIT
)
if (lineUsedColor) {
if (component != null) {
hasUsedColor = true
lines[index] = coloredLine.toString()
}
}
return if (hasUsedColor) {
colorCost
outLines.add(component)
} else {
0
outLines.add(Component.text(line))
}
}
fun uncolorLines(player: Permissible, lines: ArrayList<String>, editType: LoreEditType): Int {
if (!editType.shouldRemoveColorOnLoreRemoval) return 0
return if (hasUsedColor) colorCost
else 0
}
fun uncolorLines(player: Permissible, lines: MutableList<Component?>, 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) {
@ -298,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<Component?>, 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
}
}
}

View file

@ -0,0 +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 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)
}
}

View file

@ -17,9 +17,9 @@ 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"
const val REMOVE_COLOR_COST = "remove_color_cost"
// Lore order config path
@ -42,9 +42,9 @@ 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
const val DEFAULT_REMOVE_COLOR_COST = 0
// Lore order config default

View file

@ -3,14 +3,14 @@ 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
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
@ -79,27 +79,35 @@ 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 or removal of minimessage on lore add
*/
val allowMinimessage: Boolean
get() {
return CONFIG
.config
.getBoolean("${rootPath}.$ALLOW_MINIMESSAGE", DEFAULT_ALLOW_MINIMESSAGE)
}
/**
* Cost when using either color code and hex color on lore add
*/
@ -114,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
*/

View file

@ -59,8 +59,12 @@ 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
# Toggle if color should only be applicable if the player a certain permission.
#
@ -301,9 +305,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/
#
# Note that currently minimessage would disable hex code when adding color
allow_color_code: true
allow_hexadecimal_color: true
use_cost: 0
allow_hexadecimal_color: false
allow_minimessage: true
remove:
# If removing lore using book & quil is enabled
@ -318,16 +325,25 @@ 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/
allow_color_code: true
allow_hexadecimal_color: false
allow_minimessage: true
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"
order: end
append_line:
# If adding lore line using paper is enabled
@ -344,8 +360,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/
#
# 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
remove_line:
@ -359,10 +379,19 @@ 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/
allow_color_code: true
allow_hexadecimal_color: false
allow_minimessage: true
# Whether to show debug logging
debug_log: false

View file

@ -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

View file

@ -29,9 +29,11 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Map;
// TODO redo test as now color split should be handled in AnvilColorUtilTest and not here
// Especially since some behavior changed
public class LoreEditTests extends SharedCustomAnvilTest {
private static AnvilInventory anvil;
/*private static AnvilInventory anvil;
private static PlayerMock player;
private static final String COLORED_LORE_LINE = "§x§1§2§3§4§5§6TEST §atest";
@ -289,9 +291,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 +439,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 +482,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);
@ -618,6 +617,6 @@ public class LoreEditTests extends SharedCustomAnvilTest {
).executeTest(anvil, player);
}
//TODO work penalty test
//TODO work penalty test*/
}