Merge pull request #34 from l4zs/master

use the adventure api
This commit is contained in:
Jakob K
2022-01-14 21:36:55 +01:00
committed by GitHub
11 changed files with 163 additions and 82 deletions

View File

@@ -3,21 +3,21 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
val githubRepo = "jakobkmar/KSpigot"
group = "net.axay"
version = "1.18.0"
version = "1.18.1"
description = "A Kotlin API for Minecraft plugins using the Spigot or Paper toolchain"
plugins {
kotlin("jvm") version "1.6.0"
kotlin("jvm") version "1.6.10"
`java-library`
`maven-publish`
signing
id("org.jetbrains.dokka") version "1.6.0"
kotlin("plugin.serialization") version "1.6.0"
id("org.jetbrains.dokka") version "1.6.10"
kotlin("plugin.serialization") version "1.6.10"
id("io.papermc.paperweight.userdev") version "1.3.1"
id("io.papermc.paperweight.userdev") version "1.3.3"
}
repositories {
@@ -27,9 +27,9 @@ repositories {
dependencies {
paperDevBundle("1.18.1-R0.1-SNAPSHOT")
api("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.1")
api("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0-RC2")
api("org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:1.6.0-RC2")
api("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.2")
api("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0")
api("org.jetbrains.kotlinx:kotlinx-coroutines-jdk8:1.6.0")
}
tasks {

View File

@@ -1,13 +1,18 @@
@file:Suppress("MemberVisibilityCanBePrivate", "unused")
@file:Suppress("MemberVisibilityCanBePrivate", "Unused")
package net.axay.kspigot.chat
import net.md_5.bungee.api.ChatColor
import net.md_5.bungee.api.chat.BaseComponent
import net.md_5.bungee.api.chat.ClickEvent
import net.md_5.bungee.api.chat.HoverEvent
import net.md_5.bungee.api.chat.TextComponent
import net.md_5.bungee.api.chat.hover.content.Text
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].
@@ -18,10 +23,10 @@ import net.md_5.bungee.api.chat.hover.content.Text
inline fun literalText(
baseText: String = "",
builder: LiteralTextBuilder.() -> Unit = { }
) = LiteralTextBuilder(baseText).apply(builder).build() as TextComponent
) = LiteralTextBuilder(baseText).apply(builder).build()
class LiteralTextBuilder(val internalText: BaseComponent, ) {
constructor(text: String) : this(TextComponent(text))
class LiteralTextBuilder(val internalText: Component) {
constructor(text: String) : this(Component.text(text))
var bold: Boolean? = null
var italic: Boolean? = null
@@ -39,12 +44,12 @@ class LiteralTextBuilder(val internalText: BaseComponent, ) {
* - `color = col("#4BD6CB")`
* - `color = KColors.MEDIUMTURQUOISE`
*/
var color: ChatColor? = null
var color: TextColor? = null
var clickEvent: ClickEvent? = null
var hoverEvent: HoverEvent? = null
var hoverEvent: HoverEvent<*>? = null
val siblingText = TextComponent("")
var siblingText = empty()
/**
* Append text to the parent.
@@ -56,20 +61,20 @@ class LiteralTextBuilder(val internalText: BaseComponent, ) {
text: String = "",
builder: LiteralTextBuilder.() -> Unit = { }
) {
siblingText.addExtra(LiteralTextBuilder(text).apply(builder).build())
siblingText = siblingText.append(LiteralTextBuilder(text).apply(builder).build())
}
/**
* Append text to the parent.
* Append a component to the parent.
*
* @param text the text instance
* @param component the component
* @param builder the builder which can be used to set the style and add child text components
*/
inline fun text(
text: BaseComponent,
inline fun component(
component: Component,
builder: LiteralTextBuilder.() -> Unit = { }
) {
siblingText.addExtra(LiteralTextBuilder(text).apply(builder).build())
siblingText = siblingText.append(LiteralTextBuilder(component).apply(builder).build())
}
/**
@@ -84,9 +89,7 @@ class LiteralTextBuilder(val internalText: BaseComponent, ) {
text: String,
builder: LiteralTextBuilder.() -> Unit = { }
) {
TextComponent.fromLegacyText(text).forEach {
siblingText.addExtra(LiteralTextBuilder(it).apply(builder).build())
}
siblingText = siblingText.append(LiteralTextBuilder(LegacyComponentSerializer.legacy('§').deserialize(text)).apply(builder).build())
}
/**
@@ -100,12 +103,36 @@ class LiteralTextBuilder(val internalText: BaseComponent, ) {
text: String = "",
builder: LiteralTextBuilder.() -> Unit = { }
) {
hoverEvent = HoverEvent(
hoverEvent = HoverEvent.hoverEvent(
HoverEvent.Action.SHOW_TEXT,
Text(arrayOf(LiteralTextBuilder(text).apply(builder).build()))
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.
@@ -115,7 +142,7 @@ class LiteralTextBuilder(val internalText: BaseComponent, ) {
* instead it will be suggested in the command prompt
*/
fun onClickCommand(command: String, onlySuggest: Boolean = false) {
clickEvent = ClickEvent(if (onlySuggest) ClickEvent.Action.SUGGEST_COMMAND else ClickEvent.Action.RUN_COMMAND, command)
clickEvent = if (onlySuggest) ClickEvent.suggestCommand(command) else ClickEvent.runCommand(command)
}
/**
@@ -123,14 +150,21 @@ class LiteralTextBuilder(val internalText: BaseComponent, ) {
* Player clicks on this text.
*/
fun onClickCopy(copyText: String) {
clickEvent = ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, copyText)
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.addExtra(TextComponent("\n"))
siblingText = siblingText.append(newline())
}
/**
@@ -141,17 +175,24 @@ class LiteralTextBuilder(val internalText: BaseComponent, ) {
newLine()
}
fun build() = internalText.apply {
this@LiteralTextBuilder.bold?.let { isBold = it }
this@LiteralTextBuilder.italic?.let { isItalic = it }
this@LiteralTextBuilder.underline?.let { isUnderlined = it }
this@LiteralTextBuilder.strikethrough?.let { isStrikethrough = it }
this@LiteralTextBuilder.obfuscate?.let { isObfuscated = it }
this@LiteralTextBuilder.color?.let { color = it }
this@LiteralTextBuilder.clickEvent?.let { clickEvent = it }
this@LiteralTextBuilder.hoverEvent?.let { hoverEvent = it }
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)) }
if (siblingText.extra?.isNotEmpty() == true)
addExtra(siblingText)
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)
}
}
}

View File

@@ -1,12 +1,13 @@
@file:Suppress("MemberVisibilityCanBePrivate")
@file:Suppress("MemberVisibilityCanBePrivate", "Unused")
package net.axay.kspigot.chat
import net.md_5.bungee.api.chat.BaseComponent
import net.kyori.adventure.text.Component
import net.kyori.adventure.text.JoinConfiguration
import org.bukkit.command.CommandSender
fun CommandSender.sendMessage(vararg components: BaseComponent) {
this.spigot().sendMessage(*components)
fun CommandSender.sendMessage(vararg components: Component) {
this.sendMessage(Component.join(JoinConfiguration.separator(Component.newline()), *components))
}
/**
@@ -18,7 +19,7 @@ fun CommandSender.sendMessage(vararg components: BaseComponent) {
inline fun CommandSender.sendText(
baseText: String = "",
crossinline builder: LiteralTextBuilder.() -> Unit = { }
) = this.spigot().sendMessage(literalText(baseText, builder))
) = this.sendMessage(literalText(baseText, builder))
@Suppress("DEPRECATION")
@Deprecated(

View File

@@ -1,4 +1,4 @@
@file:Suppress("MemberVisibilityCanBePrivate")
@file:Suppress("MemberVisibilityCanBePrivate", "Unused")
package net.axay.kspigot.chat.input
@@ -8,6 +8,8 @@ import net.axay.kspigot.chat.input.implementations.PlayerInputChat
import net.axay.kspigot.event.unregister
import net.axay.kspigot.runnables.sync
import net.axay.kspigot.runnables.taskRunLater
import net.kyori.adventure.text.Component
import net.kyori.adventure.text.Component.text
import org.bukkit.entity.Player
import org.bukkit.event.Listener
@@ -16,13 +18,25 @@ import org.bukkit.event.Listener
* chat input of the player as his input.
*/
fun Player.awaitChatInput(
question: String = "Type your input in the chat!",
question: Component = text("Type your input in the chat!"),
timeoutSeconds: Int = 1 * 60,
callback: (PlayerInputResult<String>) -> Unit,
callback: (PlayerInputResult<Component>) -> Unit,
) {
PlayerInputChat(this, callback, timeoutSeconds, question)
}
/**
* Asks the player a question and uses the next
* chat input of the player as his input.
*/
fun Player.awaitChatInput(
question: String = "Type your input in the chat!",
timeoutSeconds: Int = 1 * 60,
callback: (PlayerInputResult<Component>) -> Unit,
) {
awaitChatInput(text(question), timeoutSeconds, callback)
}
/**
* Opens a book and uses the text the player inserted
* on all sites as the players' input.
@@ -41,7 +55,7 @@ fun Player.awaitBookInputAsString(
*/
fun Player.awaitBookInputAsList(
timeoutSeconds: Int = 1 * 60,
callback: (PlayerInputResult<List<String>>) -> Unit,
callback: (PlayerInputResult<List<Component>>) -> Unit,
) = PlayerInputBookPaged(this, callback, timeoutSeconds).bookItemStack
/**

View File

@@ -7,6 +7,7 @@ import net.axay.kspigot.extensions.bukkit.content
import net.axay.kspigot.items.itemStack
import net.axay.kspigot.items.meta
import net.axay.kspigot.main.PluginInstance
import net.kyori.adventure.text.Component
import org.bukkit.Material
import org.bukkit.NamespacedKey
import org.bukkit.entity.Player
@@ -24,10 +25,10 @@ internal class PlayerInputBookComprehensive(
internal class PlayerInputBookPaged(
player: Player,
callback: (PlayerInputResult<List<String>>) -> Unit,
callback: (PlayerInputResult<List<Component>>) -> Unit,
timeoutSeconds: Int,
) : PlayerInputBook<List<String>>(player, callback, timeoutSeconds) {
override fun loadBookContent(bookMeta: BookMeta): List<String> = bookMeta.pages
) : PlayerInputBook<List<Component>>(player, callback, timeoutSeconds) {
override fun loadBookContent(bookMeta: BookMeta): List<Component> = bookMeta.pages()
}
internal abstract class PlayerInputBook<T>(

View File

@@ -1,28 +1,28 @@
package net.axay.kspigot.chat.input.implementations
import net.axay.kspigot.chat.KColors
import io.papermc.paper.event.player.AsyncChatEvent
import net.axay.kspigot.chat.input.PlayerInput
import net.axay.kspigot.chat.input.PlayerInputResult
import net.axay.kspigot.event.listen
import net.kyori.adventure.text.Component
import org.bukkit.entity.Player
import org.bukkit.event.EventPriority
import org.bukkit.event.player.AsyncPlayerChatEvent
internal class PlayerInputChat(
player: Player,
callback: (PlayerInputResult<String>) -> Unit,
callback: (PlayerInputResult<Component>) -> Unit,
timeoutSeconds: Int,
question: String,
) : PlayerInput<String>(player, callback, timeoutSeconds) {
question: Component,
) : PlayerInput<Component>(player, callback, timeoutSeconds) {
init {
player.sendMessage("${KColors.ORANGERED}$question")
player.sendMessage(question)
}
override val inputListeners = listOf(
listen<AsyncPlayerChatEvent>(EventPriority.LOWEST) {
listen<AsyncChatEvent>(EventPriority.LOWEST) {
if (it.player == player) {
onReceive(it.message())
it.isCancelled = true
onReceive(it.message)
}
}
)

View File

@@ -1,6 +1,9 @@
@file:Suppress("Unused")
package net.axay.kspigot.extensions
import net.axay.kspigot.main.PluginInstance
import net.kyori.adventure.text.Component.text
import org.bukkit.Bukkit
import org.bukkit.NamespacedKey
import org.bukkit.World
@@ -36,7 +39,7 @@ val pluginManager get() = Bukkit.getPluginManager()
* @return the number of recipients
* @see Bukkit.broadcastMessage
*/
fun broadcast(msg: String) = Bukkit.broadcastMessage(msg)
fun broadcast(msg: String) = Bukkit.getServer().broadcast(text(msg))
/**
* Shortcut to get the ConsoleSender.

View File

@@ -1,3 +1,5 @@
@file:Suppress("Unused")
package net.axay.kspigot.extensions.bukkit
import net.axay.kspigot.annotations.NMS_General
@@ -5,7 +7,6 @@ import net.axay.kspigot.chat.literalText
import net.axay.kspigot.extensions.onlinePlayers
import net.axay.kspigot.main.PluginInstance
import net.axay.kspigot.pluginmessages.PluginMessageConnect
import net.md_5.bungee.api.ChatMessageType
import org.bukkit.Location
import org.bukkit.Material
import org.bukkit.attribute.Attribute
@@ -146,7 +147,7 @@ fun Player.getHandItem(hand: EquipmentSlot?) = when (hand) {
* Sends the given [text] as an action bar message.
*/
fun Player.actionBar(text: String) {
spigot().sendMessage(ChatMessageType.ACTION_BAR, literalText { legacyText(text) })
sendActionBar(literalText { legacyText(text) })
}
/**

View File

@@ -1,11 +1,12 @@
package net.axay.kspigot.extensions.bukkit
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer
import org.bukkit.inventory.meta.BookMeta
val BookMeta.content
get() =
StringBuilder().apply {
for (it in pages) {
for (it in pages().map { LegacyComponentSerializer.legacy('§').serialize(it) }) {
if (isNotEmpty())
append('\n')
append(it)

View File

@@ -1,7 +1,8 @@
@file:Suppress("MemberVisibilityCanBePrivate", "CanBeParameter")
@file:Suppress("MemberVisibilityCanBePrivate", "CanBeParameter", "Unused")
package net.axay.kspigot.gui
import net.kyori.adventure.text.Component.text
import org.bukkit.Bukkit
import org.bukkit.event.inventory.InventoryType
import org.bukkit.inventory.Inventory
@@ -27,8 +28,8 @@ class GUIType<in T : ForInventory>(
fun createBukkitInv(holder: InventoryHolder? = null, title: String? = null): Inventory {
val realTitle = title ?: ""
return when {
bukkitType != null -> Bukkit.createInventory(holder, bukkitType, realTitle)
else -> Bukkit.createInventory(holder, dimensions.slotAmount, realTitle)
bukkitType != null -> Bukkit.createInventory(holder, bukkitType, text(realTitle))
else -> Bukkit.createInventory(holder, dimensions.slotAmount, text(realTitle))
}
}
}

View File

@@ -1,5 +1,11 @@
@file:Suppress("Unused")
package net.axay.kspigot.items
import net.kyori.adventure.text.Component
import net.kyori.adventure.text.Component.text
import net.kyori.adventure.text.Component.translatable
import net.kyori.adventure.text.TranslatableComponent
import org.bukkit.Bukkit
import org.bukkit.Material
import org.bukkit.inventory.ItemFlag
@@ -58,16 +64,16 @@ inline fun itemMeta(material: Material, builder: ItemMeta.() -> Unit) = itemMeta
* Sets the lore (description) of the item.
*/
inline fun ItemMeta.setLore(builder: ItemMetaLoreBuilder.() -> Unit) {
lore = ItemMetaLoreBuilder().apply(builder).lorelist
lore(ItemMetaLoreBuilder().apply(builder).lorelist)
}
/**
* Adds new lines to the lore (description) of the item.
*/
inline fun ItemMeta.addLore(builder: ItemMetaLoreBuilder.() -> Unit) {
val newLore = lore ?: mutableListOf<String>()
val newLore = lore() ?: mutableListOf<Component>()
newLore.addAll(ItemMetaLoreBuilder().apply(builder).lorelist)
lore = newLore
lore(newLore)
}
/**
@@ -75,10 +81,13 @@ inline fun ItemMeta.addLore(builder: ItemMetaLoreBuilder.() -> Unit) {
* It exists to provide overloaded operator functions.
*/
class ItemMetaLoreBuilder {
val lorelist = ArrayList<String>()
operator fun String.unaryPlus() {
val lorelist = ArrayList<Component>()
operator fun Component.unaryPlus() {
lorelist += this
}
operator fun String.unaryPlus() {
lorelist += text(this)
}
}
/**
@@ -104,7 +113,16 @@ fun ItemMeta.removeFlags(vararg itemFlag: ItemFlag) = removeItemFlags(*itemFlag)
/**
* Provides safe access to the items' displayName.
*/
var ItemMeta.name: String?
var ItemMeta.name: Component?
get() = if (hasDisplayName()) displayName() else null
set(value) = displayName(value ?: Component.space())
/**
* Provides safe access to the items' displayName.
*/
@Suppress("DEPRECATION")
@Deprecated("displaynames are saved as Components in Paper", ReplaceWith("name", "net.axay.kspigot.Items.name"))
var ItemMeta.stringName: String?
get() = if (hasDisplayName()) displayName else null
set(value) = setDisplayName(if (value == null || value == "") " " else value)
@@ -118,6 +136,6 @@ var ItemMeta.customModel: Int?
/**
* Provides more consistent access to the items' localizedName.
*/
var ItemMeta.localName: String
get() = localizedName
set(value) = setLocalizedName(value)
var ItemMeta.localName: TranslatableComponent
get() = if (hasDisplayName()) displayName() as TranslatableComponent else translatable("")
set(value) = displayName(value)