package nl.kallestruik.dlib.gui import kotlinx.coroutines.runBlocking import net.kyori.adventure.text.Component import org.bukkit.Material import org.bukkit.entity.Player import org.bukkit.event.EventHandler import org.bukkit.event.HandlerList import org.bukkit.event.Listener import org.bukkit.event.inventory.* import org.bukkit.inventory.InventoryView import org.bukkit.inventory.ItemStack import org.bukkit.plugin.Plugin fun textInputDialog(player: Player, plugin: Plugin, configure: suspend TextInputDialog.() -> Unit) { val textInputDialog = TextInputDialog() runBlocking { textInputDialog.configure() } textInputDialog.display(player, plugin) } class TextInputDialog: Listener { private data class Configuration( var item: suspend TextInputDialogItem.() -> Unit = {}, var onFinish: suspend (value: String) -> Unit = {}, var onCancel: suspend () -> Unit = {} ) private val configuration = Configuration() var prompt: Component = Component.empty() private lateinit var view: InventoryView private lateinit var plugin: Plugin fun item(entry: suspend TextInputDialogItem.() -> Unit) { configuration.item = entry } fun onFinish(onFinish: suspend (value: String) -> Unit) { configuration.onFinish = onFinish } fun onCancel(onCancel: suspend () -> Unit) { configuration.onCancel = onCancel } fun display(player: Player, plugin: Plugin) { player.closeInventory() this.plugin = plugin view = player.openAnvil(null, true) ?: return val entry = TextInputDialogItem() runBlocking { configuration.item.invoke(entry) } val itemStack = ItemStack(entry.material, entry.amount) val itemMeta = itemStack.itemMeta itemMeta.displayName(prompt) itemStack.itemMeta = itemMeta view.setItem(0, itemStack) plugin.server.pluginManager.registerEvents(this, plugin) } private fun cleanup() { view.close() HandlerList.unregisterAll(this) } /* Bukkit event handlers */ @EventHandler fun onInventoryClose(event: InventoryCloseEvent) { if (event.view != this.view) return if (event.reason == InventoryCloseEvent.Reason.PLUGIN) { return } runBlocking { configuration.onCancel.invoke() cleanup() } } @EventHandler fun onAnvilPrepare(event: PrepareAnvilEvent) { if (event.view != view) return // Always keep the cost at 1. 0 Causes the client to not be able to click it. event.inventory.repairCost = 1 } @EventHandler fun onOperationFinish(event: InventoryClickEvent) { if (event.view != view) { return } if (event.action != InventoryAction.PICKUP_ALL) { event.isCancelled = true return } if (view.convertSlot(event.rawSlot) != 2) { event.isCancelled = true return } val item = event.currentItem val name = item?.itemMeta?.displayName ?: "" if (name == "") { event.isCancelled = true return } event.isCancelled = true runBlocking { configuration.onFinish.invoke(name) cleanup() } } } data class TextInputDialogItem( var material: Material = Material.AIR, var amount: Int = 1, )