lore edit color should work

This commit is contained in:
alexcrea 2025-03-17 14:07:44 +01:00
parent 5f3eed08e2
commit 074313fb7c
No known key found for this signature in database
GPG key ID: 43FD265DB0DBF91F
5 changed files with 259 additions and 45 deletions

View file

@ -30,6 +30,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 kotlin.collections.ArrayList
import kotlin.math.min
class AnvilResultListener : Listener {
@ -348,13 +349,15 @@ class AnvilResultListener : Listener {
// fill book meta
val meta = leftItem.itemMeta
if (meta == null || !meta.hasLore()) return false
val lore = meta.lore!!
val lore = ArrayList<String>(meta.lore!!)
if (lore.isEmpty()) return false
// Uncolor the page
AnvilLoreEditUtil.uncolorLines(player, lore, LoreEditType.REMOVE_BOOK)
val bookPage = StringBuilder()
lore.forEach {
if (bookPage.isNotEmpty()) bookPage.append('\n')
//TODO check & do color
bookPage.append(it)
}
@ -426,10 +429,15 @@ class AnvilResultListener : Listener {
if (lore.isEmpty()) return false
val removeEnd = LoreEditConfigUtil.paperLoreOrderIsEnd
//TODO check & do color
val line = if (removeEnd) lore[lore.size - 1]
var 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]
// Create result item
val rightClone = rightItem.clone()
rightClone.amount = 1

View file

@ -80,7 +80,7 @@ class PrepareAnvilListener : Listener {
}
// return true if a custom recipe exist with these ingredient
// return true if a custom recipe exist with these ingredients
private fun testCustomRecipe(event: PrepareAnvilEvent, inventory: AnvilInventory,
player: HumanEntity,
first: ItemStack, second: ItemStack?): Boolean {
@ -134,7 +134,10 @@ class PrepareAnvilListener : Listener {
if(ConfigOptions.renameColorPossible && inventoryName != null){
val resultString = StringBuilder(inventoryName)
useColor = AnvilColorUtil.handleRenamingColor(resultString, player)
useColor = AnvilColorUtil.handleColor(resultString, player,
ConfigOptions.permissionNeededForColor,
ConfigOptions.allowColorCode, ConfigOptions.allowHexadecimalColor,
AnvilColorUtil.ColorUseType.RENAME)
if(useColor) {
inventoryName = resultString.toString()

View file

@ -1,38 +1,99 @@
package xyz.alexcrea.cuanvil.util
import io.delilaheve.util.ConfigOptions
import org.bukkit.entity.HumanEntity
import org.bukkit.permissions.Permissible
import java.util.regex.Matcher
import java.util.regex.Pattern
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
fun handleRenamingColor(textToColor: StringBuilder, player: HumanEntity): Boolean {
val usePermission = ConfigOptions.permissionNeededForColor
val canUseColorCode = ConfigOptions.allowColorCode && (!usePermission || player.hasPermission("ca.color.code"))
val canUseHexColor = ConfigOptions.allowHexadecimalColor && (!usePermission || player.hasPermission("ca.color.hex"))
/**
* 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,
player: Permissible,
usePermission: Boolean,
allowColorCode: Boolean,
allowHexadecimalColor: Boolean,
useType: ColorUseType
): Boolean {
if (!allowColorCode && !allowHexadecimalColor) return false
if((!canUseColorCode) && (!canUseHexColor)) return false
val canUseColorCode =
allowColorCode && (!usePermission || useType.colorCodePerm == null || player.hasPermission(
useType.colorCodePerm
))
val canUseHexColor =
allowHexadecimalColor && (!usePermission || useType.hexColorPerm == null || player.hasPermission(
useType.hexColorPerm
))
if ((!canUseColorCode) && (!canUseHexColor)) return false
var useColor = false
// Handle color code
if(canUseColorCode){
if (canUseColorCode) {
var nbReplacement = replaceAll(textToColor, "&", "§", 2)
nbReplacement -= 2 * replaceAll(textToColor, "§§", "&", 2)
if(nbReplacement > 0) useColor = true
if (nbReplacement > 0) useColor = true
}
if(canUseHexColor){
if (canUseHexColor) {
val nbReplacement = replaceHexToColor(textToColor, 7)
if(nbReplacement > 0) useColor = true
if (nbReplacement > 0) useColor = true
}
return useColor
}
/**
* 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
*/
fun revertColor(
colorToText: StringBuilder,
player: Permissible,
usePermission: Boolean,
allowColorCode: Boolean,
allowHexadecimalColor: Boolean,
useType: ColorUseType
): Boolean {
if (!allowColorCode && !allowHexadecimalColor) return false
val canUseColorCode =
allowColorCode && (!usePermission || useType.colorCodePerm == null || player.hasPermission(
useType.colorCodePerm
))
val canUseHexColor =
allowHexadecimalColor && (!usePermission || useType.hexColorPerm == null || player.hasPermission(
useType.hexColorPerm
))
if ((!canUseColorCode) && (!canUseHexColor)) return false
var hasReversed = false
// Reverse hex pattern
if (canUseHexColor) {
val nbReplacement = replaceHexToColor(colorToText, 14)
if (nbReplacement > 0) hasReversed = true
}
if (canUseColorCode) {
replaceAll(colorToText, "&", "&&", 1)
val nbReplacement = replaceAll(colorToText, "§", "&", 2)
if (nbReplacement > 0) hasReversed = true
}
return hasReversed
}
/**
* Replace every instance of "from" to "to".
* @param builder The builder to replace the string from.
@ -50,7 +111,7 @@ object AnvilColorUtil {
index += to.length
index = builder.indexOf(from, index)
numberOfChanges+=1
numberOfChanges += 1
}
return numberOfChanges
@ -68,21 +129,58 @@ object AnvilColorUtil {
var numberOfChanges = 0
var startIndex = 0
while(matcher.find(startIndex)){
while (matcher.find(startIndex)) {
startIndex = matcher.start()
if(startIndex >= builder.length - endOffset) break
if (startIndex >= builder.length - endOffset) break //HOW AND WHERE WOULD THIS HAPPEN ?????
builder.replace(startIndex, startIndex + 1, "§x")
startIndex+=2
startIndex += 2
for (i in 0..5) {
builder.insert(startIndex, '§')
startIndex+=2
startIndex += 2
}
numberOfChanges+=1
numberOfChanges += 1
}
return numberOfChanges
}
/**
* Replace every hex color from the minecraft format to a format like #000000
* @param builder The builder to replace the minecraft hex color from.
* @param endOffset Amount of character that should be ignored at the end.
* @return The number of replacement was that was done.
*/
private fun replaceColorToHex(builder: StringBuilder, endOffset: Int): Int {
val matcher: Matcher = TRANSFORMED_HEX_PATTERN.matcher(builder)
var numberOfChanges = 0
var startIndex = 0
while (matcher.find(startIndex)) {
startIndex = matcher.start()
if (startIndex >= builder.length - endOffset) break //HOW AND WHERE WOULD THIS HAPPEN ?????
builder.replace(startIndex, startIndex + 2, "#")
startIndex += 1
for (i in 0..5) {
builder.deleteCharAt(startIndex)
startIndex += 1
}
numberOfChanges += 1
}
return numberOfChanges
}
enum class ColorUseType(
val colorCodePerm: String?,
val hexColorPerm: String?
) {
RENAME("ca.color.code", "ca.color.hex"),
LORE_EDIT(null, null)
}
}

View file

@ -30,21 +30,26 @@ object AnvilLoreEditUtil {
if (!hasLoreEditByBookPermission(player)) return null
val result = first.clone()
val meta = result.itemMeta?: return null
val meta = result.itemMeta ?: return null
val lore = if (meta.hasLore()) {
ArrayList<String>(meta.lore!!)
} else ArrayList()
//TODO check color if color if enabled
val lines = book.pages[0].split("\n")
val page = book.pages[0]
val lines = ArrayList<String>(page.split("\n"))
val colorCost = colorLines(player, lines, LoreEditType.APPEND_BOOK)
lore.addAll(lines)
meta.lore = lore
result.itemMeta = meta
// Handle other xp
xpCost.addAndGet(lines.size * LoreEditType.APPEND_BOOK.perLineCost)
xpCost.addAndGet(baseEditLoreXpCost(first, result, LoreEditType.APPEND_BOOK))
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(baseEditLoreXpCost(first, result, LoreEditType.APPEND_BOOK)) // Fixed cost and work penalty
return result
}
@ -54,20 +59,25 @@ object AnvilLoreEditUtil {
// remove lore
val result = first.clone()
val leftMeta = result.itemMeta?: return null
val currentLore = leftMeta.lore?: return null
val leftMeta = result.itemMeta ?: return null
val currentLore = ArrayList<String>(leftMeta.lore ?: return null)
val uncolorCost = uncolorLines(player, currentLore, LoreEditType.REMOVE_BOOK)
leftMeta.lore = null
result.itemMeta = leftMeta
// Handle other xp
if (result == first) return null
// Handle xp
xpCost.addAndGet(uncolorCost)
xpCost.addAndGet(currentLore.size * LoreEditType.REMOVE_BOOK.perLineCost)
xpCost.addAndGet(baseEditLoreXpCost(first, result, LoreEditType.REMOVE_BOOK))
return result
}
// Return true if append, false if remove, null if neither
// Return true if appended, false if removed, null if neither
fun bookLoreEditIsAppend(first: ItemStack, second: ItemStack): Boolean? {
// Test if the book & quil contain content
val meta = second.itemMeta as BookMeta? ?: return false
@ -106,7 +116,7 @@ object AnvilLoreEditUtil {
else handleLoreRemoveByBook(player, first, xpCost)
}
// Return true if append, false if remove, null if neither
// Return true if appended, false if removed, null if neither
fun paperLoreEditIsAppend(first: ItemStack, second: ItemStack): Boolean? {
// Test if the paper contain a display name
val meta = second.itemMeta ?: return false
@ -134,24 +144,31 @@ object AnvilLoreEditUtil {
if (!hasLoreEditByPaperPermission(player)) return null
val result = first.clone()
val meta = result.itemMeta
val lore = if (meta?.hasLore() == true) {
val meta = result.itemMeta?: return null
val lore = if (meta.hasLore()) {
ArrayList<String>(meta.lore!!)
} else ArrayList()
val appendEnd = LoreEditConfigUtil.paperLoreOrderIsEnd
//TODO check color if color if enabled
val line = second.itemMeta!!.displayName
// 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 line = tempList[0]
if (appendEnd)
lore.add(line)
else
lore.add(0, line)
meta?.lore = lore
meta.lore = lore
result.itemMeta = meta
// Handle other xp
if (result == first) return null
// Handle xp
xpCost.addAndGet(colorCost)
xpCost.addAndGet(baseEditLoreXpCost(first, result, LoreEditType.APPEND_PAPER))
return result
@ -167,13 +184,21 @@ object AnvilLoreEditUtil {
val removeEnd = LoreEditConfigUtil.paperLoreOrderIsEnd
val lore: ArrayList<String> = ArrayList(meta.lore!!)
if (removeEnd) lore.removeAt(lore.size - 1)
val line = if (removeEnd) lore.removeAt(lore.size - 1)
else lore.removeAt(0)
meta.lore = if (lore.isEmpty()) null else lore
result.itemMeta = meta
// Get color cost to uncolor this line
val tempList = ArrayList<String>(1)
tempList.add(line)
val uncolorCost = uncolorLines(player, tempList, LoreEditType.REMOVE_PAPER)
if (result == first) return null
// Handle other xp
xpCost.addAndGet(uncolorCost)
xpCost.addAndGet(baseEditLoreXpCost(first, result, LoreEditType.REMOVE_PAPER))
return result
@ -202,4 +227,86 @@ object AnvilLoreEditUtil {
return xpCost
}
private fun colorLines(player: Permissible, lines: ArrayList<String>, useType: LoreEditType): Int {
val canUseHex: Boolean
val canUseColorCode: Boolean
val colorCost: Int
// If is book
if (useType == LoreEditType.REMOVE_BOOK || useType == LoreEditType.APPEND_BOOK) {
canUseHex = LoreEditConfigUtil.bookAllowHexColor
canUseColorCode = LoreEditConfigUtil.bookAllowColorCode
colorCost = LoreEditConfigUtil.bookUseColorCost
} // Else if is paper
else {
canUseHex = LoreEditConfigUtil.paperAllowHexColor
canUseColorCode = LoreEditConfigUtil.paperAllowColorCode
colorCost = LoreEditConfigUtil.paperUseColorCost
}
// Now handle color of each lines
var hasUsedColor = false
for ((index, line) in lines.withIndex()) {
val coloredLine = StringBuilder(line)
val lineUsedColor = AnvilColorUtil.handleColor(
coloredLine,
player,
false, canUseColorCode, canUseHex,
AnvilColorUtil.ColorUseType.LORE_EDIT
)
if (lineUsedColor) {
hasUsedColor = true
lines[index] = coloredLine.toString()
}
}
return if (hasUsedColor) {
colorCost
} else {
0
}
}
fun uncolorLines(player: Permissible, lines: ArrayList<String>, useType: LoreEditType): Int {
val canUseHex: Boolean
val canUseColorCode: Boolean
val colorCost: Int
// If is book
if (useType == LoreEditType.REMOVE_BOOK || useType == LoreEditType.APPEND_BOOK) {
canUseHex = LoreEditConfigUtil.bookAllowHexColor
canUseColorCode = LoreEditConfigUtil.bookAllowColorCode
colorCost = LoreEditConfigUtil.bookUseColorCost
} // Else if is paper
else {
canUseHex = LoreEditConfigUtil.paperAllowHexColor
canUseColorCode = LoreEditConfigUtil.paperAllowColorCode
colorCost = LoreEditConfigUtil.paperUseColorCost
}
// Now handle color of each lines
var hasUndidColor = false
for ((index, line) in lines.withIndex()) {
val uncoloredLine = StringBuilder(line)
val lineUndidColor = AnvilColorUtil.revertColor(
uncoloredLine,
player,
false, canUseColorCode, canUseHex,
AnvilColorUtil.ColorUseType.LORE_EDIT
)
if (lineUndidColor) {
hasUndidColor = true
lines[index] = uncoloredLine.toString()
}
}
return if (hasUndidColor) {
colorCost
} else {
0
}
}
}

View file

@ -8,8 +8,6 @@ object LoreEditConfigUtil {
const val IS_ENABLED = "enabled"
const val FIXED_COST = "fixed_cost"
const val PER_LINE_COST = "per_line_cost"
const val USE_COST_PENALTY = "use_cost_penalty"
const val INCREASE_COST_PENALTY = "increase_cost_penalty"
const val DO_CONSUME = "do_consume"
// Permission configs path
@ -61,8 +59,8 @@ object LoreEditConfigUtil {
val FIXED_COST_RANGE = 0..1000
val PER_LINE_COST_RANGE = 0..1000
val COLOR_BOOK_COST_RANGE = 0..1000
val COLOR_PAPER_COST_RANGE = 0..1000
private val COLOR_BOOK_COST_RANGE = 0..1000
private val COLOR_PAPER_COST_RANGE = 0..1000
// -------------------
// Generic Get methods