diff --git a/api/.gradle/caches/paperweight/taskCache/reobfJar.log b/api/.gradle/caches/paperweight/taskCache/reobfJar.log index ef38c4b..db7dd04 100644 --- a/api/.gradle/caches/paperweight/taskCache/reobfJar.log +++ b/api/.gradle/caches/paperweight/taskCache/reobfJar.log @@ -1,2 +1,2 @@ Command: C:\Program Files\Java\jdk-17\bin\java.exe -Xmx1G -classpath C:\Users\Mangr\.gradle\caches\modules-2\files-2.1\net.fabricmc\tiny-remapper\0.10.1\c293b2384ae12af74f407fa3aaa553bba4ac6763\tiny-remapper-0.10.1-fat.jar net.fabricmc.tinyremapper.Main D:\PC\Projects\KtBukkitGui\api\build\libs\ktgui-2.4.1-dev-all.jar D:\PC\Projects\KtBukkitGui\api\build\libs\api-2.4.1.jar C:\Users\Mangr\.gradle\caches\paperweight-userdev\ff775525efc29c3503a07d1006e63e5695a742b7505cf63e157d49d32419c69f\module\io.papermc.paper\dev-bundle\1.20.4-R0.1-SNAPSHOT\paperweight\setupCache\extractDevBundle.dir\data\mojang+yarn-spigot-reobf.tiny mojang+yarn spigot C:\Users\Mangr\.gradle\caches\paperweight-userdev\ff775525efc29c3503a07d1006e63e5695a742b7505cf63e157d49d32419c69f\module\io.papermc.paper\dev-bundle\1.20.4-R0.1-SNAPSHOT\paperweight\setupCache\applyMojangMappedPaperclipPatch.jar --threads=1 -Finished after 2771.45 ms. +Finished after 2784.17 ms. diff --git a/api/src/main/kotlin/com/mattmx/ktgui/components/button/ButtonClickedEvent.kt b/api/src/main/kotlin/com/mattmx/ktgui/components/button/ButtonClickedEvent.kt index 526ab2a..93961b0 100644 --- a/api/src/main/kotlin/com/mattmx/ktgui/components/button/ButtonClickedEvent.kt +++ b/api/src/main/kotlin/com/mattmx/ktgui/components/button/ButtonClickedEvent.kt @@ -4,6 +4,7 @@ import com.mattmx.ktgui.GuiManager import com.mattmx.ktgui.extensions.getOpenGui import com.mattmx.ktgui.item.DslIBuilder import com.mattmx.ktgui.item.builder +import net.kyori.adventure.text.Component import org.bukkit.Material import org.bukkit.entity.Player import org.bukkit.event.Cancellable @@ -52,6 +53,8 @@ data class ButtonClickedEvent>( override fun setCancelled(cancel: Boolean) = shouldContinueCallback(!cancel) + fun reply(component: Component) = player.sendMessage(component) + fun forceClose() { GuiManager.clearGui(player) player.closeInventory() diff --git a/api/src/main/kotlin/com/mattmx/ktgui/components/button/GuiButton.kt b/api/src/main/kotlin/com/mattmx/ktgui/components/button/GuiButton.kt index d7bdde3..b981316 100644 --- a/api/src/main/kotlin/com/mattmx/ktgui/components/button/GuiButton.kt +++ b/api/src/main/kotlin/com/mattmx/ktgui/components/button/GuiButton.kt @@ -50,23 +50,23 @@ open class GuiButton>( if (item == null) item = ItemStack(material) } - open fun lore(block: MutableList.() -> Unit): T { - item?.editMeta { - val newLore = mutableListOf().apply(block) - it.lore(newLore.map { line -> Component.empty().decoration(TextDecoration.ITALIC, false).append(line) }) - } + open fun lore(block: LoreList.() -> Unit): T { + val loreList = LoreList(item?.itemMeta?.lore()).apply(block) + lore(*loreList.toTypedArray()) return this as T } @JavaCompatibility - fun lore(vararg lines: Component): T { + open fun lore(vararg lines: Component): T { item?.editMeta { - it.lore(lines.map { line -> Component.empty().decoration(TextDecoration.ITALIC, false).append(line) }) + it.lore(lines.map { line -> + Component.empty().decoration(TextDecoration.ITALIC, false).append(line) + }) } return this as T } - infix fun named(name: Component?): T { + open infix fun named(name: Component?): T { item?.editMeta { if (name != null) it?.displayName(Component.empty().decoration(TextDecoration.ITALIC, false).append(name)) @@ -80,12 +80,12 @@ open class GuiButton>( return this as T } - fun slots(vararg slots: Int): T { + open fun slots(vararg slots: Int): T { slots.forEach { slot(it) } return this as T } - fun removeSlots(vararg slot: Int): T = apply { + open fun removeSlots(vararg slot: Int): T = apply { if (hasParent()) { slots?.removeAll(slot.toSet()) parent.clearSlot(*slot) @@ -108,7 +108,7 @@ open class GuiButton>( return this as T } - fun hasParent() = this::parent.isInitialized + open fun hasParent() = this::parent.isInitialized override infix fun childOf(parent: IGuiScreen): T { this.parent = parent @@ -120,14 +120,14 @@ open class GuiButton>( } - fun materialOf(materialName: String?, fallback: Material): T { + open fun materialOf(materialName: String?, fallback: Material): T { val materialNameFormatted = materialName?.uppercase()?.replace(" ", "_") val mat = Material.values().firstOrNull { it.name == materialNameFormatted } mat?.also { material(it) } ?: material(fallback) return this as T } - infix fun material(material: Material): T { + open infix fun material(material: Material): T { item?.let { it.type = material return this as T @@ -136,19 +136,19 @@ open class GuiButton>( return this as T } - infix fun customModelData(model: Int): T { + open infix fun customModelData(model: Int): T { val meta = item?.itemMeta ?: return this as T meta.setCustomModelData(model) item?.itemMeta = meta return this as T } - infix fun amount(amount: Int): T { + open infix fun amount(amount: Int): T { item?.let { it.amount = amount } return this as T } - infix fun fromItemBuilder(builder: DslIBuilder): T { + open infix fun fromItemBuilder(builder: DslIBuilder): T { item = builder.build() return this as T } @@ -158,15 +158,11 @@ open class GuiButton>( } @JavaCompatibility - fun click(type: ClickType, block: Consumer>): T { + open fun click(type: ClickType, block: Consumer>): T { click.handleClicks({ block.accept(this) }, type) return this as T } - fun test(b: Consumer) { - - } - inline infix fun click(block: ClickCallback.() -> Unit): T { block.invoke(click) return this as T diff --git a/api/src/main/kotlin/com/mattmx/ktgui/components/button/LoreCycleButton.kt b/api/src/main/kotlin/com/mattmx/ktgui/components/button/LoreCycleButton.kt index e974d17..18d5274 100644 --- a/api/src/main/kotlin/com/mattmx/ktgui/components/button/LoreCycleButton.kt +++ b/api/src/main/kotlin/com/mattmx/ktgui/components/button/LoreCycleButton.kt @@ -4,8 +4,6 @@ import net.kyori.adventure.text.Component import net.kyori.adventure.text.format.TextDecoration import org.bukkit.entity.Player import org.bukkit.inventory.ItemStack -import kotlin.math.max -import kotlin.math.min class LoreCycleButton : GuiButton() { var selected = 0 @@ -38,7 +36,7 @@ class LoreCycleButton : GuiButton() { } @Deprecated("This should not be used in this class.", ReplaceWith("this")) - override fun lore(lore: MutableList.() -> Unit): LoreCycleButton { + override fun lore(block: LoreList.() -> Unit): LoreCycleButton { return this } diff --git a/api/src/main/kotlin/com/mattmx/ktgui/components/button/LoreList.kt b/api/src/main/kotlin/com/mattmx/ktgui/components/button/LoreList.kt new file mode 100644 index 0000000..793cf55 --- /dev/null +++ b/api/src/main/kotlin/com/mattmx/ktgui/components/button/LoreList.kt @@ -0,0 +1,11 @@ +package com.mattmx.ktgui.components.button + +import net.kyori.adventure.text.Component + +class LoreList( + existing: List? +) : ArrayList(existing ?: emptyList()) { + + operator fun Component.unaryPlus() = add(this) + +} \ No newline at end of file diff --git a/api/src/main/kotlin/com/mattmx/ktgui/components/screen/GuiScreen.kt b/api/src/main/kotlin/com/mattmx/ktgui/components/screen/GuiScreen.kt index 2fe5461..fe796e9 100644 --- a/api/src/main/kotlin/com/mattmx/ktgui/components/screen/GuiScreen.kt +++ b/api/src/main/kotlin/com/mattmx/ktgui/components/screen/GuiScreen.kt @@ -184,12 +184,12 @@ open class GuiScreen( Bukkit.getScheduler().runTask(GuiManager.owningPlugin) { -> player.openInventory(inventory) player.setOpenGui(this) - open(player) + open.invoke(player) } } else { player.openInventory(inventory) player.setOpenGui(this) - open(player) + open.invoke(player) } } } diff --git a/api/src/main/kotlin/com/mattmx/ktgui/components/screen/pagination/GuiCramMultiPageScreen.kt b/api/src/main/kotlin/com/mattmx/ktgui/components/screen/pagination/GuiCramMultiPageScreen.kt index 8d63766..153aadd 100644 --- a/api/src/main/kotlin/com/mattmx/ktgui/components/screen/pagination/GuiCramMultiPageScreen.kt +++ b/api/src/main/kotlin/com/mattmx/ktgui/components/screen/pagination/GuiCramMultiPageScreen.kt @@ -36,9 +36,9 @@ class GuiCramMultiPageScreen( } fun nextSlotToFill(sub: GuiScreen): Int? { - var nextSlot = sub.slotsUsed().max() + 1 + var nextSlot = (sub.slotsUsed().maxOrNull() ?: -1) + 1 - while (nextSlot in reservedSlots() && nextSlot <= sub.totalSlots()) { + while (nextSlot in reservedSlots() && nextSlot < sub.totalSlots()) { nextSlot++ } @@ -49,7 +49,7 @@ class GuiCramMultiPageScreen( fun isFull(sub: GuiScreen) = sub.slotsUsed().size >= totalSlots() - reservedSlots().size - fun reservedSlots() = this.slotsUsed() + extraReservedSlots + fun reservedSlots() = (this.slotsUsed() + extraReservedSlots).toSet() } diff --git a/api/src/main/kotlin/com/mattmx/ktgui/components/screen/pagination/GuiMultiPageScreen.kt b/api/src/main/kotlin/com/mattmx/ktgui/components/screen/pagination/GuiMultiPageScreen.kt index ec66403..00a7b33 100644 --- a/api/src/main/kotlin/com/mattmx/ktgui/components/screen/pagination/GuiMultiPageScreen.kt +++ b/api/src/main/kotlin/com/mattmx/ktgui/components/screen/pagination/GuiMultiPageScreen.kt @@ -1,12 +1,19 @@ package com.mattmx.ktgui.components.screen.pagination +import com.mattmx.ktgui.GuiManager +import com.mattmx.ktgui.components.button.ButtonClickedEvent +import com.mattmx.ktgui.components.button.IGuiButton import com.mattmx.ktgui.components.screen.GuiScreen import com.mattmx.ktgui.dsl.button import com.mattmx.ktgui.event.EventCallback import com.mattmx.ktgui.utils.not import net.kyori.adventure.text.Component +import org.bukkit.Bukkit import org.bukkit.Material import org.bukkit.entity.Player +import org.bukkit.event.inventory.InventoryClickEvent +import org.bukkit.inventory.Inventory +import org.bukkit.inventory.ItemStack import java.util.* import kotlin.math.max import kotlin.math.min @@ -24,8 +31,64 @@ open class GuiMultiPageScreen( val pageChange = EventCallback() val pages = Collections.synchronizedList(arrayListOf()) + override fun refresh() { + val inv = arrayOfNulls(totalSlots()) + + // Now apply the items + val current = pages.getOrNull(currentPage) + + current?.items?.forEach { (slot, item) -> + inv[slot] = item.formatIntoItemStack() + } + + items.forEach { (slot, item) -> + if (slot < inv.size) + inv[slot] = item.formatIntoItemStack() + } + + GuiManager.getPlayers(this) + .forEach { player -> + for ((index, item) in inv.withIndex()) { + player.openInventory.setItem(index, item) + } + } + } + override fun open(player: Player) { - TODO() + // format the items + val inv = Bukkit.createInventory(player, totalSlots(), title) + + if (firePreBuildEvent(player)) return + + // Now apply the items + val current = pages.getOrNull(currentPage) + + current?.items?.forEach { (slot, item) -> + inv.setItem(slot, item.formatIntoItemStack(player)) + } + + items.forEach { (slot, item) -> + if (slot < inv.size) + inv.setItem(slot, item.formatIntoItemStack(player)) + } + + openIfNotCancelled(player, inv) + } + + override fun click(e: InventoryClickEvent) { + val currentPage = pages.getOrNull(currentPage) + + val button = items[e.rawSlot] ?: currentPage?.items?.get(e.rawSlot) + + val event = ButtonClickedEvent>(e.whoClicked as Player, e) + if (button != null) + event.button = button + + click.run(event) + + if (event.shouldContinueCallback()) { + button?.onButtonClick(event) + } } infix fun page(block: GuiScreen.() -> Unit) = page(null, block) @@ -38,12 +101,20 @@ open class GuiMultiPageScreen( } } + open fun navigatePreviousPage(e: ButtonClickedEvent<*>) = navigatePreviousPage() + open fun navigateNextPage(e: ButtonClickedEvent<*>) = navigateNextPage() + open fun navigatePreviousPage() { currentPage = max(0, currentPage - 1) } open fun navigateNextPage() { - currentPage = min(pages.size, currentPage + 1) + currentPage = min(pages.size - 1, currentPage + 1) + } + + override fun destroy() { + pages.forEach { it.destroy() } + super.destroy() } } diff --git a/api/src/main/kotlin/com/mattmx/ktgui/utils/color.kt b/api/src/main/kotlin/com/mattmx/ktgui/utils/color.kt index d9cfccf..bf70407 100644 --- a/api/src/main/kotlin/com/mattmx/ktgui/utils/color.kt +++ b/api/src/main/kotlin/com/mattmx/ktgui/utils/color.kt @@ -53,3 +53,6 @@ operator fun Component.plus(component: Component) = this.append(component) infix fun Component.clickEvent(event: ClickEvent) = clickEvent(event) infix fun Component.hoverEvent(event: HoverEvent) = hoverEvent(event) operator fun String.not() = component() + +val String.translatable + get() = Component.translatable(this) diff --git a/plugin/.gradle/caches/paperweight/taskCache/reobfJar.log b/plugin/.gradle/caches/paperweight/taskCache/reobfJar.log index f2db6a9..c20b37a 100644 --- a/plugin/.gradle/caches/paperweight/taskCache/reobfJar.log +++ b/plugin/.gradle/caches/paperweight/taskCache/reobfJar.log @@ -1,2 +1,2 @@ Command: C:\Program Files\Java\jdk-17\bin\java.exe -Xmx1G -classpath C:\Users\Mangr\.gradle\caches\modules-2\files-2.1\net.fabricmc\tiny-remapper\0.10.1\c293b2384ae12af74f407fa3aaa553bba4ac6763\tiny-remapper-0.10.1-fat.jar net.fabricmc.tinyremapper.Main D:\PC\Projects\KtBukkitGui\plugin\build\libs\ktgui-plugin-2.4.1-dev-all.jar D:\PC\Projects\KtBukkitGui\plugin\build\libs\plugin-unspecified.jar C:\Users\Mangr\.gradle\caches\paperweight-userdev\ff775525efc29c3503a07d1006e63e5695a742b7505cf63e157d49d32419c69f\module\io.papermc.paper\dev-bundle\1.20.4-R0.1-SNAPSHOT\paperweight\setupCache\extractDevBundle.dir\data\mojang+yarn-spigot-reobf.tiny mojang+yarn spigot C:\Users\Mangr\.gradle\caches\paperweight-userdev\ff775525efc29c3503a07d1006e63e5695a742b7505cf63e157d49d32419c69f\module\io.papermc.paper\dev-bundle\1.20.4-R0.1-SNAPSHOT\paperweight\setupCache\applyMojangMappedPaperclipPatch.jar --threads=1 -Finished after 1940.16 ms. +Finished after 1634.00 ms. diff --git a/plugin/src/main/kotlin/com/mattmx/ktgui/KotlinGui.kt b/plugin/src/main/kotlin/com/mattmx/ktgui/KotlinGui.kt index 21af13e..d2ec71a 100644 --- a/plugin/src/main/kotlin/com/mattmx/ktgui/KotlinGui.kt +++ b/plugin/src/main/kotlin/com/mattmx/ktgui/KotlinGui.kt @@ -67,7 +67,7 @@ class KotlinGui : JavaPlugin() { "refresh-scoreboard" to { signalScoreboardExample }, "new-multi-screen-cram" to { NewCramMultiPageExample() }, "new-multi-screen" to { NewMultiPageExample() }, - "player-inventory" to { HotbarExample() } + "hotbar" to { HotbarExample() } ) GuiHookExample.registerListener(this) diff --git a/plugin/src/main/kotlin/com/mattmx/ktgui/examples/NewCramMultiPageExample.kt b/plugin/src/main/kotlin/com/mattmx/ktgui/examples/NewCramMultiPageExample.kt index dc1ef2e..6509b7d 100644 --- a/plugin/src/main/kotlin/com/mattmx/ktgui/examples/NewCramMultiPageExample.kt +++ b/plugin/src/main/kotlin/com/mattmx/ktgui/examples/NewCramMultiPageExample.kt @@ -3,24 +3,42 @@ package com.mattmx.ktgui.examples import com.mattmx.ktgui.components.screen.pagination.cramMultiPageScreen import com.mattmx.ktgui.dsl.button import com.mattmx.ktgui.utils.not +import com.mattmx.ktgui.utils.plus +import com.mattmx.ktgui.utils.translatable +import net.kyori.adventure.text.format.TextColor import org.bukkit.Material import org.bukkit.entity.Player class NewCramMultiPageExample : Example { - val gui = cramMultiPageScreen(!"Materials") { + val gui = cramMultiPageScreen(!"Materials &71") { + // These are slots that we should not cram fill with items + // In this example we're reserving the bottom row for pagination controls. reserve(last() - 8..last()) button(Material.SPECTRAL_ARROW) { named(!"&aNext") - click.left { navigateNextPage() } + click.left(::navigateNextPage) } slot last() button(Material.SPECTRAL_ARROW) { named(!"&cLast") - click.left { navigatePreviousPage() } + click.left(::navigatePreviousPage) } slot last() - 8 - +Material.values().map { button(it) {} } + pageChange { + title = !"Materials &7${currentPage + 1}" + } + + +Material.values().mapIndexed { index, material -> + button(material) { + lore { + +!"&aThis is item $index" + } + click.left { + reply(!"&aClicked " + material.translationKey().translatable + !"&a ($index)") + } + } + } } override fun run(player: Player) = gui.open(player) diff --git a/plugin/src/main/kotlin/com/mattmx/ktgui/examples/NewMultiPageExample.kt b/plugin/src/main/kotlin/com/mattmx/ktgui/examples/NewMultiPageExample.kt index 5c10c10..70e7760 100644 --- a/plugin/src/main/kotlin/com/mattmx/ktgui/examples/NewMultiPageExample.kt +++ b/plugin/src/main/kotlin/com/mattmx/ktgui/examples/NewMultiPageExample.kt @@ -8,22 +8,33 @@ import org.bukkit.entity.Player class NewMultiPageExample : Example { val gui = multiPageGui(!"Test") { + button(Material.SPECTRAL_ARROW) { named(!"&aLast") click.left { navigatePreviousPage() } - } slot last() + } slot last() - 7 button(Material.SPECTRAL_ARROW) { named(!"&aNext") click.left { navigateNextPage() } - } slot last() + } slot last() - 1 page { - button(Material.BEACON) { named(!"Page 1 test") } slot middle() + button(Material.BEACON) { + named(!"Page 1 Item") + click.left { + reply(!"&aClicked page 1 item") + } + } slot middle() // for some reason middle() is incorrect? } page { - button(Material.NETHER_STAR) { named(!"Page 2 test") } slot middle() + button(Material.NETHER_STAR) { + named(!"Page 2 Item") + click.left { + reply(!"&aClicked page 2 item") + } + } slot middle() } }