Files
KSpigot/src/main/kotlin/net/axay/kspigot/chat/LiteralTextBuilder.kt
l4zs 9c008dcba4 use the adventure api
- migrate BungeeCord Chat API to Adventure API
- add some functions to literalText
- update some dependencies and plugins
2022-01-09 18:18:32 +01:00

199 lines
6.4 KiB
Kotlin

@file:Suppress("MemberVisibilityCanBePrivate", "Unused")
package net.axay.kspigot.chat
import net.kyori.adventure.text.Component
import net.kyori.adventure.text.Component.empty
import net.kyori.adventure.text.Component.newline
import net.kyori.adventure.text.event.ClickEvent
import net.kyori.adventure.text.event.HoverEvent
import net.kyori.adventure.text.format.TextColor
import net.kyori.adventure.text.format.TextColor.color
import net.kyori.adventure.text.format.TextDecoration
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer
import org.bukkit.entity.Entity
import org.bukkit.inventory.ItemStack
/**
* Opens a [LiteralTextBuilder].
*
* @param baseText the text you want to begin with, it is okay to let this empty
* @param builder the builder which can be used to set the style and add child text components
*/
inline fun literalText(
baseText: String = "",
builder: LiteralTextBuilder.() -> Unit = { }
) = LiteralTextBuilder(baseText).apply(builder).build()
class LiteralTextBuilder(val internalText: Component) {
constructor(text: String) : this(Component.text(text))
var bold: Boolean? = null
var italic: Boolean? = null
var underline: Boolean? = null
var strikethrough: Boolean? = null
var obfuscate: Boolean? = null
/**
* The text color.
* This can be set in the following way:
*
* e.g. Medium turquoise:
* - `color = col(0x4BD6CB)`
* - `color = col(4970187)`
* - `color = col("#4BD6CB")`
* - `color = KColors.MEDIUMTURQUOISE`
*/
var color: TextColor? = null
var clickEvent: ClickEvent? = null
var hoverEvent: HoverEvent<*>? = null
var siblingText = empty()
/**
* Append text to the parent.
*
* @param text the raw text (without formatting)
* @param builder the builder which can be used to set the style and add child text components
*/
inline fun text(
text: String = "",
builder: LiteralTextBuilder.() -> Unit = { }
) {
siblingText = siblingText.append(LiteralTextBuilder(text).apply(builder).build())
}
/**
* Append a component to the parent.
*
* @param component the component
* @param builder the builder which can be used to set the style and add child text components
*/
inline fun component(
component: Component,
builder: LiteralTextBuilder.() -> Unit = { }
) {
siblingText = siblingText.append(LiteralTextBuilder(component).apply(builder).build())
}
/**
* Append the given legacy text to the parent. This
* allows you to use legacy color codes (e.g. `§c` for red).
* It is **not** recommended to use this.
*
* @param text the text instance
* @param builder the builder which can be used to set the style and add child text components
*/
inline fun legacyText(
text: String,
builder: LiteralTextBuilder.() -> Unit = { }
) {
siblingText = siblingText.append(LiteralTextBuilder(LegacyComponentSerializer.legacy('§').deserialize(text)).apply(builder).build())
}
/**
* Sets the text which should be displayed when hovering
* over the text in the chat.
*
* @param text the raw text (without formatting)
* @param builder the builder which can be used to set the style and add child text components
*/
inline fun hoverText(
text: String = "",
builder: LiteralTextBuilder.() -> Unit = { }
) {
hoverEvent = HoverEvent.hoverEvent(
HoverEvent.Action.SHOW_TEXT,
LiteralTextBuilder(text).apply(builder).build()
)
}
/**
* Sets the item which should be displayed when hovering
* over the text in the chat.
*
* @param itemStack the ItemStack
*/
fun hoverItem(
itemStack: ItemStack
) {
hoverEvent = itemStack.asHoverEvent()
}
/**
* Sets the entity which should be displayed when hovering
* over the text in the chat.
*
* @param entity the Entity
*/
fun hoverEntity(
entity: Entity
) {
hoverEvent = entity.asHoverEvent()
}
/**
* Sets the command which should be executed by the Player if he clicks
* on the text.
*
* @param command the command which should be executed, the `/ should be added here
* @param onlySuggest if true, the command won't be executed immediately,
* instead it will be suggested in the command prompt
*/
fun onClickCommand(command: String, onlySuggest: Boolean = false) {
clickEvent = if (onlySuggest) ClickEvent.suggestCommand(command) else ClickEvent.runCommand(command)
}
/**
* Sets the String which should be copied to the clipboard if the
* Player clicks on this text.
*/
fun onClickCopy(copyText: String) {
clickEvent = ClickEvent.copyToClipboard(copyText)
}
/**
* Sets the Url which should be opened if the Player clicks on this text
*/
fun onClickOpenURL(url: String) {
clickEvent = ClickEvent.openUrl(url)
}
/**
* Adds a line break.
*/
fun newLine() {
siblingText = siblingText.append(newline())
}
/**
* Adds an empty line.
*/
fun emptyLine() {
newLine()
newLine()
}
fun build(): Component {
var style = internalText.style()
val decorations = style.decorations().toMutableMap()
decorations[TextDecoration.BOLD] = TextDecoration.State.byBoolean(this@LiteralTextBuilder.bold)
decorations[TextDecoration.ITALIC] = TextDecoration.State.byBoolean(this@LiteralTextBuilder.italic)
decorations[TextDecoration.UNDERLINED] = TextDecoration.State.byBoolean(this@LiteralTextBuilder.underline)
decorations[TextDecoration.STRIKETHROUGH] = TextDecoration.State.byBoolean(this@LiteralTextBuilder.strikethrough)
decorations[TextDecoration.OBFUSCATED] = TextDecoration.State.byBoolean(this@LiteralTextBuilder.obfuscate)
style = style.decorations(decorations)
this@LiteralTextBuilder.color?.let { style = style.color(color(it)) }
this@LiteralTextBuilder.clickEvent?.let { style = style.clickEvent(it) }
this@LiteralTextBuilder.hoverEvent?.let { style = style.hoverEvent(it) }
return if (siblingText.children().isNotEmpty()) {
internalText.append(siblingText).style(style)
} else {
internalText.style(style)
}
}
}