Ignore formatting colors when parsing shop signs
MrPowerGamerBR opened this issue · 4 comments
Is your feature request related to a problem? Please describe.
I always wanted to use formatting colors because plain black colored shop signs are boooring, something like:
§1Player Name
Quantity
§aB 10§f:§4S 10
§9Item Name
However, while you could set the colors on the sign via an external plugin, ChestShop ends up not recognizing the sign ("The shop cannot be used!"), even if the text itself is still the same, because ChestShop doesn't strip the chat colors from the sign lines before trying to parse it.
So it would be nice if ChestShop ignored formatting codes when parsing the sign, to allow custom colors on the sign lines themselves.
Describe the solution you'd like
Strip chat colors from signs before parsing them via ChestShop. I don't think this would cause issues with current shops (in my experience, I didn't have any). Doing this would also open new doors for features like the one described in #365.
Currently I use my own fork to do this:
But it could be better, my version is too hacky and non customizable.
Describe alternatives you've considered
While players can already dye their shop signs, but in this case I want to set the color themselves to be consistent.
Dyed signs work because the sign color is not set via formatting colors on the sign lines, they are set in the sign NBT itself.
Agreements
- I have checked if there are already similar issues open.
- I have checked that the latest build doesn't already implement the feature.
Additional context
thanks for reading :3
The commit should now at least allow shops which's lines had formatting added externally but creating it with formatting directly on the sign will still not be possible due to the plugin setting the lines to non-formatted ones on creation. I'm unsure if this should/can be allowed moving forward with format-able signs or if a global formatting config like requested in other places previously would be a better (and cleaner) way to handle that.
This is kinda related to #237 too I guess.
@Phoenix616 I tested it with a very simple event handler that listens to the PreShopCreationEvent
and then prepends chat colors to each line:
@EventHandler(priority = EventPriority.MONITOR)
fun onChange(e: PreShopCreationEvent) {
e.setSignLine(0, "§1" + e.getSignLine(0))
e.setSignLine(1, "§e" + e.getSignLine(1))
e.setSignLine(2, "§a" + e.getSignLine(2))
e.setSignLine(3, ChatColor.of(Color(179, 255, 219)).toString() + e.getSignLine(3)) // let's throw a RGB color in here too why not
e.signLines.forEach {
println(it.replace("§", "&"))
}
}
(would be nice if the API supported Adventure components but hey if it works I ain't complaining 😛)
And it seems that it works fine! :3 I only wanted to colorize the signs, but keep the sign formatting, so your changes are already good enough for me.
However I haven't tested on my public server yet to see if there are going to be any issues there, but I think this will work fine for my needs! If I end up finding any issues when testing it on my public server I will be sure to tell it here.
But yeah: For non programmers it would be nice if there was a configuration section to set the color formatting there.
But thanks for implementing this! Now I don't need to keep my hacky ChestShop fork :3
And here's a very barebones implementation of @bricefrisco's original idea described in #365 :3 It only checks if the shop doesn't have B
stock in the chest, not S
space in the chest, but that shouldn't be hard to implement in the code.
chestshop.colored.signs.idea.mp4
class ColorizeShopSignsListener(val m: DreamChestShopStuff) : Listener {
// https://github.com/ChestShop-authors/ChestShop-3/issues/503
@EventHandler(priority = EventPriority.MONITOR)
fun onPreShopCreation(event: PreShopCreationEvent) {
val itemTradedByShop: ItemStack = StockCounterModule.determineItemTradedByShop(event.getSignLine(ITEM_LINE))
val chestShopInventory: Inventory = uBlock.findConnectedContainer(event.sign).inventory
val numTradedItemsInChest: Int = InventoryUtil.getAmount(itemTradedByShop, chestShopInventory)
if (numTradedItemsInChest == 0) {
event.signLines = event.signLines
.map {
"§c" + ChatColor.stripColor(it)
}.toTypedArray()
} else {
// Owner
event.setSignLine(0, "§1" + ChatColor.stripColor(event.getSignLine(0)))
// Price
event.setSignLine(
2,
ChatColor.stripColor(event.getSignLine(2))
.replace("B", "§aB")
.replace(":", "§0:")
.replace("S", "§4S")
)
// Item
event.setSignLine(3, "§9" + ChatColor.stripColor(event.getSignLine(3)))
}
}
@EventHandler
fun onInventoryClose(event: InventoryCloseEvent) {
val inventoryLocation = event.inventory.location
if (inventoryLocation == null || !ChestShopSign.isShopBlock(inventoryLocation.block))
return
for (shopSign in uBlock.findConnectedShopSigns(event.inventory.holder)) {
if (ChestShopSign.isAdminShop(shopSign))
return
updateSignColorBasedOnStockQuantity(shopSign, event.inventory)
}
}
@EventHandler(priority = EventPriority.HIGH)
fun onTransaction(event: TransactionEvent) {
if (ChestShopSign.isAdminShop(event.sign))
return
for (shopSign in uBlock.findConnectedShopSigns(event.ownerInventory.holder)) {
updateSignColorBasedOnStockQuantity(shopSign, event.ownerInventory)
}
}
// From the StockCounterModule class
private fun updateSignColorBasedOnStockQuantity(sign: Sign, chestShopInventory: Inventory?) {
val itemTradedByShop: ItemStack = StockCounterModule.determineItemTradedByShop(sign) ?: return
val numTradedItemsInChest: Int = InventoryUtil.getAmount(itemTradedByShop, chestShopInventory)
if (numTradedItemsInChest == 0) {
// No items in the chest, make everything red!
for (i in 0 until 4) {
sign.setLine(i, "§c" + ChatColor.stripColor(sign.getLine(i)))
}
} else {
// Items in the chest, update it to be our custom ChestShop sign color!
// Owner
sign.setLine(0, "§1" + ChatColor.stripColor(sign.getLine(0)))
// Quantity
sign.setLine(1, ChatColor.stripColor(sign.getLine(1)))
// Price
sign.setLine(
2,
ChatColor.stripColor(sign.getLine(2))
.replace("B", "§aB")
.replace(":", "§0:")
.replace("S", "§4S")
)
// Item
sign.setLine(3, "§9" + ChatColor.stripColor(sign.getLine(3)))
}
// TODO: We could check if the sign really needs to be updated, instead of calling the update method every time
sign.update(true)
}
}
@Phoenix616 tested the new ChestShop version on my public server, and they seem to have worked fine! 😊
I also made some changes to my previous code example:
- Implemented the colored sign, just like how it was shown in the issue
- Implemented the original idea explained in #365:
- Users can colorize their username with dyes
- Users can make their username rainbow in the sign using one of my server's custom items (rainbow wool)
- Admin Shops have a different username colorization compared to player made shops
Of course, my changes are tailored to my own server, however if anyone is stumbling upon this issue wondering how I implemented those changes, here it is (the repo is licensed under AGPL-3.0 but tbh do whatever you want with the code I don't really care, just that if you do something cool and epic with the ChestShop signs please share with everyone 😄): https://github.com/SparklyPower/SparklyPower/blob/624ab68f178e380c5902634045d4dee5d69da09e/bukkit/DreamChestShopStuff/src/main/kotlin/net/perfectdreams/dreamchestshopstuff/listeners/ColorizeShopSignsListener.kt#L34
Anyway, thank you @Phoenix616, this may seem like a small change in the grand scheme of things but it really makes the ChestShop signs be more colorful and fun to the players! If I end up finding an issue, I will reopen the issue :)
(PS: I sent a smol tip for you for implementing this :3, thank you for maintaining ChestShop)