@file:Suppress("MemberVisibilityCanBePrivate") package net.axay.kspigot.chat.input import net.axay.kspigot.chat.input.implementations.PlayerInputAnvilInv import net.axay.kspigot.chat.input.implementations.PlayerInputBookComprehensive import net.axay.kspigot.chat.input.implementations.PlayerInputBookPaged 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 org.bukkit.entity.Player import org.bukkit.event.Listener /** * 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) -> Unit, ) { PlayerInputChat(this, callback, timeoutSeconds, question) } /** * Opens an anvil GUI and uses the new name of the * renamed item as the players' input. */ fun Player.awaitAnvilInput( invTitle: String = "Type your input!", startText: String = "RENAME ME", renameItemDescription: List = listOf( "Rename this item to", "submit your input!" ), timeoutSeconds: Int = 1 * 60, callback: (PlayerInputResult) -> Unit, ) { PlayerInputAnvilInv(this, callback, timeoutSeconds, invTitle, startText, renameItemDescription) } /** * Opens a book and uses the text the player inserted * on all sites as the players' input. * In this case, all pages will be flattened to a single string. */ fun Player.awaitBookInputAsString( timeoutSeconds: Int = 1 * 60, callback: (PlayerInputResult) -> Unit, ) { PlayerInputBookComprehensive(this, callback, timeoutSeconds) } /** * Opens a book and uses the text the player inserted * on all sites as the players' input. * In this case, every page is represented by one string * element in a list of strings. */ fun Player.awaitBookInputAsList( timeoutSeconds: Int = 1 * 60, callback: (PlayerInputResult>) -> Unit, ) { PlayerInputBookPaged(this, callback, timeoutSeconds) } /** * @param input The input the player gave. Null on timeout or invalid input. */ class PlayerInputResult internal constructor(val input: T?) internal abstract class PlayerInput( protected val player: Player, private val callback: (PlayerInputResult) -> Unit, timeoutSeconds: Int, ) { private var received = false protected abstract val inputListeners: List protected fun onReceive(input: T?) { if (!received) { inputListeners.forEach { it.unregister() } received = true sync { callback.invoke(PlayerInputResult(input)) } } } open fun onTimeout() {} init { taskRunLater(delay = (20 * timeoutSeconds).toLong()) { if (!received) onTimeout() onReceive(null) } } }