diff --git a/build.gradle.kts b/build.gradle.kts index 8b1894a4..62bf1325 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -58,7 +58,7 @@ dependencies { testCompileOnly("org.spigotmc", "spigot", "1.16.3-R0.1-SNAPSHOT") // KHTTP - implementation("khttp", "khttp", "1.0.0") + api("khttp", "khttp", "1.0.0") } diff --git a/src/main/kotlin/net/axay/kspigot/config/ConfigManager.kt b/src/main/kotlin/net/axay/kspigot/config/ConfigManager.kt index 33c78ab9..5e621579 100644 --- a/src/main/kotlin/net/axay/kspigot/config/ConfigManager.kt +++ b/src/main/kotlin/net/axay/kspigot/config/ConfigManager.kt @@ -2,7 +2,7 @@ package net.axay.kspigot.config -import net.axay.kspigot.languageextensions.createIfNotExists +import net.axay.kspigot.languageextensions.kotlinextensions.createIfNotExists import net.axay.kspigot.main.ValueHolder.getGson import java.io.File import java.io.FileReader diff --git a/src/main/kotlin/net/axay/kspigot/inventory/InventoryGUI.kt b/src/main/kotlin/net/axay/kspigot/inventory/InventoryGUI.kt index 72a16650..b049faed 100644 --- a/src/main/kotlin/net/axay/kspigot/inventory/InventoryGUI.kt +++ b/src/main/kotlin/net/axay/kspigot/inventory/InventoryGUI.kt @@ -2,76 +2,9 @@ package net.axay.kspigot.inventory -import net.axay.kspigot.event.listen -import org.bukkit.entity.HumanEntity -import org.bukkit.event.inventory.InventoryClickEvent import org.bukkit.inventory.Inventory -import org.bukkit.inventory.InventoryView import org.bukkit.inventory.ItemStack -// EXTENSIONS - -fun HumanEntity.openGUI(gui: InventoryGUI<*>, page: Int? = null): InventoryView? { - - closeInventory() - - if (page != null) - gui.loadPageUnsafe(page) - - return openInventory(gui.bukkitInventory) - -} - -// GUI HOLDER - -object InventoryGUIHolder : AutoCloseable { - - private val registered = HashSet>() - - fun register(inventoryGUI: InventoryGUI) { - registered.add(inventoryGUI) - } - - fun unregister(inventoryGUI: InventoryGUI) { - registered.remove(inventoryGUI) - } - - init { - - listen { - - val clickedInv = it.clickedInventory ?: return@listen - - val inv = registered.find { search -> search.isThisInv(clickedInv) } ?: return@listen - val invPage = inv.currentPageInt - - val slot = inv.data.pages[invPage]?.slots?.get(it.slot) - if (slot != null) - slot.onClick(InventoryGUIClickEvent(it, inv)) - else - it.isCancelled = true - - } - } - - override fun close() { - registered.forEach { inv -> inv.bukkitInventory.viewers.forEach { it.closeInventory() } } - registered.clear() - } - -} - -// EVENT - -class InventoryGUIClickEvent( - val bukkitEvent: InventoryClickEvent, - val gui: InventoryGUI -) - -/* - * INVENTORY GUI - */ - private const val DEFAULT_PAGE = 1 class InventoryGUIData( @@ -94,13 +27,25 @@ abstract class InventoryGUI( internal abstract val bukkitInventory: Inventory + internal var isInMove: Boolean = false + + internal abstract fun loadPageUnsafe( + page: Int, + offsetHorizontally: Int = 0, + offsetVertically: Int = 0 + ) + internal abstract fun loadPageUnsafe( page: InventoryGUIPage<*>, offsetHorizontally: Int = 0, offsetVertically: Int = 0 ) - internal abstract fun loadPageUnsafe(page: Int, offsetHorizontally: Int = 0, offsetVertically: Int = 0) + internal abstract fun loadContent( + content: Map>, + offsetHorizontally: Int = 0, + offsetVertically: Int = 0 + ) /** * @return True, if the [inventory] belongs to this GUI. @@ -136,6 +81,14 @@ abstract class InventoryGUI( */ fun getPage(page: Int?) = data.pages[page] + /** + * Reloads the current page. + */ + fun reloadCurrentPage() { + if (!isInMove) + loadPage(currentPage) + } + } // Inventory GUI implementations @@ -152,43 +105,59 @@ class InventoryGUIShared( override fun isThisInv(inventory: Inventory) = inventory == bukkitInventory + override fun loadPageUnsafe(page: Int, offsetHorizontally: Int, offsetVertically: Int) { + data.pages[page]?.let { loadPageUnsafe(it, offsetHorizontally, offsetVertically) } + } + override fun loadPageUnsafe(page: InventoryGUIPage<*>, offsetHorizontally: Int, offsetVertically: Int) { val ifOffset = offsetHorizontally != 0 || offsetVertically != 0 - if (!ifOffset) + if (!ifOffset) { + + // unregister this inv from all elements on the previous page + HashSet(currentPage.slots.values).forEach { if (it is InventoryGUIElement) it.stopUsing(this) } + currentPageInt = page.number - page.slots.let { slots -> + } - val dimensions = data.inventoryType.dimensions + loadContent(page.slots, offsetHorizontally, offsetVertically) - if (ifOffset) { - dimensions.invSlots.forEach { - dimensions.invSlotsWithRealSlots[it.add(offsetHorizontally, offsetVertically)]?.let { slotToClear -> - if (dimensions.realSlots.contains(slotToClear)) - bukkitInventory.clear(slotToClear) - } - } - } else { - bukkitInventory.clear() + } + + override fun loadContent( + content: Map>, + offsetHorizontally: Int, + offsetVertically: Int + ) { + + val ifOffset = offsetHorizontally != 0 || offsetVertically != 0 + + val dimensions = data.inventoryType.dimensions + + // clear the space which will be redefined + if (ifOffset) { + dimensions.invSlots.forEach { + val slotToClear = dimensions.invSlotsWithRealSlots[it.add(offsetHorizontally, offsetVertically)] + if (slotToClear != null) bukkitInventory.clear(slotToClear) } + } else bukkitInventory.clear() - slots.forEach { - val slot = it.value - if (slot is InventoryGUIElement) { + content.forEach { - if (ifOffset) { - val invSlot = InventorySlot.fromRealSlot(it.key, dimensions) - if (invSlot != null) { - val offsetSlot = invSlot.add(offsetHorizontally, offsetVertically).realSlotIn(dimensions) - if (offsetSlot != null) - bukkitInventory.setItem(offsetSlot, slot.inventoryGUIElementData.itemStack) - } - } else { - bukkitInventory.setItem(it.key, slot.inventoryGUIElementData.itemStack) + val slot = it.value + if (slot is InventoryGUIElement) { + + if (ifOffset) { + val invSlot = InventorySlot.fromRealSlot(it.key, dimensions) + if (invSlot != null) { + val offsetSlot = invSlot.add(offsetHorizontally, offsetVertically).realSlotIn(dimensions) + if (offsetSlot != null) bukkitInventory.setItem(offsetSlot, slot.getItemStack(offsetSlot)) } - + } else { + bukkitInventory.setItem(it.key, slot.getItemStack(it.key)) + slot.startUsing(this) } } @@ -197,21 +166,10 @@ class InventoryGUIShared( } - override fun loadPageUnsafe(page: Int, offsetHorizontally: Int, offsetVertically: Int) { - data.pages[page]?.let { loadPageUnsafe(it, offsetHorizontally, offsetVertically) } - } - override operator fun set(slot: InventorySlotCompound, value: ItemStack) { slot.realSlotsWithInvType(data.inventoryType).forEach { bukkitInventory.setItem(it, value) } } -} - -class InventoryGUIPage( - val number: Int, - internal val slots: Map>, - val transitionTo: PageChangeEffect?, - val transitionFrom: PageChangeEffect? -) \ No newline at end of file +} \ No newline at end of file diff --git a/src/main/kotlin/net/axay/kspigot/inventory/InventoryGUIBuilder.kt b/src/main/kotlin/net/axay/kspigot/inventory/InventoryGUIBuilder.kt index 13a37055..1a287aaf 100644 --- a/src/main/kotlin/net/axay/kspigot/inventory/InventoryGUIBuilder.kt +++ b/src/main/kotlin/net/axay/kspigot/inventory/InventoryGUIBuilder.kt @@ -5,13 +5,15 @@ package net.axay.kspigot.inventory import net.axay.kspigot.inventory.elements.* import org.bukkit.inventory.ItemStack -fun inventoryGUI( +fun kSpigotGUI( type: InventoryType, + shared: Boolean = true, builder: InventoryGUIBuilder.() -> Unit, -) = InventoryGUIBuilder(type).apply(builder).build() +) = InventoryGUIBuilder(type, shared).apply(builder).build() class InventoryGUIBuilder( - val type: InventoryType + val type: InventoryType, + val shared: Boolean ) { var title: String = "" @@ -36,14 +38,17 @@ class InventoryGUIBuilder( onClickElement = onClick } - internal fun build() = InventoryGUIShared( - InventoryGUIData(type, title, guiSlots, transitionTo, transitionFrom, onClickElement) - ).apply { register() } + internal fun build(): InventoryGUI { + val guiData = InventoryGUIData(type, title, guiSlots, transitionTo, transitionFrom, onClickElement) + val gui = + if (shared) InventoryGUIShared(guiData) else TODO("Currently, there is no non-shared GUI implementation available.") + return gui.apply { register() } + } } class InventoryGUIPageBuilder( - val type: InventoryType, + private val type: InventoryType, val page: Int ) { @@ -60,14 +65,14 @@ class InventoryGUIPageBuilder( * function is invoked. */ fun button(slots: InventorySlotCompound, itemStack: ItemStack, onClick: (InventoryGUIClickEvent) -> Unit) = - defineSlots(slots, InventoryGUIButton(InventoryGUIElementData(itemStack), onClick)) + defineSlots(slots, InventoryGUIButton(itemStack, onClick)) /** * An item protected from any player actions. * This is not a button. */ fun placeholder(slots: InventorySlotCompound, itemStack: ItemStack) = - defineSlots(slots, InventoryGUIPlaceholder(InventoryGUIElementData(itemStack))) + defineSlots(slots, InventoryGUIPlaceholder(itemStack)) /** * A free slot does not block any player actions. @@ -87,7 +92,7 @@ class InventoryGUIPageBuilder( onChange: ((InventoryGUIClickEvent) -> Unit)? = null ) = defineSlots( slots, InventoryGUIButtonPageChange( - InventoryGUIElementData(itemStack), + itemStack, InventoryGUIPageChangeCalculator.InventoryGUIConsistentPageCalculator(toPage), onChange ) @@ -104,7 +109,7 @@ class InventoryGUIPageBuilder( onChange: ((InventoryGUIClickEvent) -> Unit)? = null ) = defineSlots( slots, InventoryGUIButtonPageChange( - InventoryGUIElementData(itemStack), + itemStack, InventoryGUIPageChangeCalculator.InventoryGUIPreviousPageCalculator, onChange ) @@ -121,7 +126,7 @@ class InventoryGUIPageBuilder( onChange: ((InventoryGUIClickEvent) -> Unit)? = null ) = defineSlots( slots, InventoryGUIButtonPageChange( - InventoryGUIElementData(itemStack), + itemStack, InventoryGUIPageChangeCalculator.InventoryGUINextPageCalculator, onChange ) @@ -139,13 +144,37 @@ class InventoryGUIPageBuilder( onChange: ((InventoryGUIClickEvent) -> Unit)? = null ) = defineSlots( slots, InventoryGUIButtonInventoryChange( - InventoryGUIElementData(itemStack), + itemStack, newGUI, newPage, onChange ) ) + /** + * Defines an area where the content of the given compound + * is displayed. + */ + fun compoundSpace( + slots: InventorySlotCompound, + compound: InventoryGUISpaceCompound + ) { + compound.addSlots(slots) + defineSlots( + slots, + InventoryGUISpaceCompoundElement(compound) + ) + } + + /** + * Creates a new compound, holding data which can be displayed + * in any compound space. + */ + fun createCompound( + iconGenerator: (E) -> ItemStack, + onClick: (clickEvent: InventoryGUIClickEvent, element: E) -> Unit + ) = InventoryGUISpaceCompound(type, iconGenerator, onClick) + private fun defineSlots(slots: InventorySlotCompound, element: InventoryGUISlot) = slots.withInvType(type).forEach { curSlot -> curSlot.realSlotIn(type.dimensions)?.let { guiSlots[it] = element } diff --git a/src/main/kotlin/net/axay/kspigot/inventory/InventoryGUIClickEvent.kt b/src/main/kotlin/net/axay/kspigot/inventory/InventoryGUIClickEvent.kt new file mode 100644 index 00000000..02bb9c3c --- /dev/null +++ b/src/main/kotlin/net/axay/kspigot/inventory/InventoryGUIClickEvent.kt @@ -0,0 +1,8 @@ +package net.axay.kspigot.inventory + +import org.bukkit.event.inventory.InventoryClickEvent + +class InventoryGUIClickEvent( + val bukkitEvent: InventoryClickEvent, + val gui: InventoryGUI +) \ No newline at end of file diff --git a/src/main/kotlin/net/axay/kspigot/inventory/InventoryGUIElements.kt b/src/main/kotlin/net/axay/kspigot/inventory/InventoryGUIElements.kt index 119372fa..5e25a874 100644 --- a/src/main/kotlin/net/axay/kspigot/inventory/InventoryGUIElements.kt +++ b/src/main/kotlin/net/axay/kspigot/inventory/InventoryGUIElements.kt @@ -8,13 +8,9 @@ abstract class InventoryGUISlot { // ELEMENT -class InventoryGUIElementData( - val itemStack: ItemStack -) +abstract class InventoryGUIElement : InventoryGUISlot() { -abstract class InventoryGUIElement( - val inventoryGUIElementData: InventoryGUIElementData -) : InventoryGUISlot() { + abstract fun getItemStack(slot: Int): ItemStack final override fun onClick(clickEvent: InventoryGUIClickEvent) { clickEvent.gui.data.generalOnClick?.invoke(clickEvent) @@ -23,4 +19,7 @@ abstract class InventoryGUIElement( protected abstract fun onClickElement(clickEvent: InventoryGUIClickEvent) + internal open fun startUsing(gui: InventoryGUI<*>) { } + internal open fun stopUsing(gui: InventoryGUI<*>) { } + } \ No newline at end of file diff --git a/src/main/kotlin/net/axay/kspigot/inventory/InventoryGUIExtensions.kt b/src/main/kotlin/net/axay/kspigot/inventory/InventoryGUIExtensions.kt new file mode 100644 index 00000000..dadceb6d --- /dev/null +++ b/src/main/kotlin/net/axay/kspigot/inventory/InventoryGUIExtensions.kt @@ -0,0 +1,15 @@ +package net.axay.kspigot.inventory + +import org.bukkit.entity.HumanEntity +import org.bukkit.inventory.InventoryView + +fun HumanEntity.openGUI(gui: InventoryGUI<*>, page: Int? = null): InventoryView? { + + closeInventory() + + if (page != null) + gui.loadPageUnsafe(page) + + return openInventory(gui.bukkitInventory) + +} \ No newline at end of file diff --git a/src/main/kotlin/net/axay/kspigot/inventory/InventoryGUIHolder.kt b/src/main/kotlin/net/axay/kspigot/inventory/InventoryGUIHolder.kt new file mode 100644 index 00000000..bfa44903 --- /dev/null +++ b/src/main/kotlin/net/axay/kspigot/inventory/InventoryGUIHolder.kt @@ -0,0 +1,47 @@ +package net.axay.kspigot.inventory + +import net.axay.kspigot.event.listen +import org.bukkit.event.inventory.InventoryClickEvent + +object InventoryGUIHolder : AutoCloseable { + + private val registered = HashSet>() + + fun register(inventoryGUI: InventoryGUI) { + registered.add(inventoryGUI) + } + + fun unregister(inventoryGUI: InventoryGUI) { + registered.remove(inventoryGUI) + } + + init { + + listen { + + val clickedInv = it.clickedInventory ?: return@listen + + val inv = registered.find { search -> search.isThisInv(clickedInv) } ?: return@listen + + if (inv.isInMove) { + it.isCancelled = true + return@listen + } + + val invPage = inv.currentPageInt + + val slot = inv.data.pages[invPage]?.slots?.get(it.slot) + if (slot != null) + slot.onClick(InventoryGUIClickEvent(it, inv)) + else + it.isCancelled = true + + } + } + + override fun close() { + registered.forEach { inv -> inv.bukkitInventory.viewers.forEach { it.closeInventory() } } + registered.clear() + } + +} \ No newline at end of file diff --git a/src/main/kotlin/net/axay/kspigot/inventory/InventoryGUIPage.kt b/src/main/kotlin/net/axay/kspigot/inventory/InventoryGUIPage.kt new file mode 100644 index 00000000..baf16b54 --- /dev/null +++ b/src/main/kotlin/net/axay/kspigot/inventory/InventoryGUIPage.kt @@ -0,0 +1,8 @@ +package net.axay.kspigot.inventory + +class InventoryGUIPage( + val number: Int, + internal val slots: Map>, + val transitionTo: PageChangeEffect?, + val transitionFrom: PageChangeEffect? +) \ No newline at end of file diff --git a/src/main/kotlin/net/axay/kspigot/inventory/InventoryGUIPageChange.kt b/src/main/kotlin/net/axay/kspigot/inventory/InventoryGUIPageChange.kt index b777da7b..e18597c6 100644 --- a/src/main/kotlin/net/axay/kspigot/inventory/InventoryGUIPageChange.kt +++ b/src/main/kotlin/net/axay/kspigot/inventory/InventoryGUIPageChange.kt @@ -67,7 +67,7 @@ internal fun InventoryGUI<*>.changePage( PageChangeEffect.SLIDE_VERTICALLY -> { - val height = data.inventoryType.dimensions.heigth + val height = data.inventoryType.dimensions.height changePageEffect(fromPageInt, toPageInt, height) { currentOffset, ifInverted -> if (ifInverted) { @@ -97,7 +97,7 @@ internal fun InventoryGUI<*>.changePage( PageChangeEffect.SWIPE_VERTICALLY -> { - val height = data.inventoryType.dimensions.heigth + val height = data.inventoryType.dimensions.height changePageEffect(fromPageInt, toPageInt, height) { currentOffset, ifInverted -> if (ifInverted) { diff --git a/src/main/kotlin/net/axay/kspigot/inventory/InventoryGUISlots.kt b/src/main/kotlin/net/axay/kspigot/inventory/InventoryGUISlots.kt index c90e906e..e82bc7b9 100644 --- a/src/main/kotlin/net/axay/kspigot/inventory/InventoryGUISlots.kt +++ b/src/main/kotlin/net/axay/kspigot/inventory/InventoryGUISlots.kt @@ -2,15 +2,17 @@ package net.axay.kspigot.inventory -import net.axay.kspigot.languageextensions.MinMaxPair +import net.axay.kspigot.languageextensions.kotlinextensions.MinMaxPair // INVENTORY -data class InventoryDimensions(val width: Int, val heigth: Int) { +data class InventoryDimensions(val width: Int, val height: Int) { + + val slotAmount = width * height val invSlots by lazy { ArrayList().apply { - (1..heigth).forEach { row -> + (1..height).forEach { row -> (1..width).forEach { slotInRow -> this += InventorySlot(row, slotInRow) } @@ -18,14 +20,6 @@ data class InventoryDimensions(val width: Int, val heigth: Int) { } } - val realSlots by lazy { - ArrayList().apply { - invSlots.forEach { curSlot -> - curSlot.realSlotIn(this@InventoryDimensions)?.let { this += it } - } - } - } - val invSlotsWithRealSlots by lazy { HashMap().apply { invSlots.forEach { curSlot -> @@ -34,6 +28,8 @@ data class InventoryDimensions(val width: Int, val heigth: Int) { } } + val realSlots by lazy { invSlotsWithRealSlots.values } + } // SLOTS @@ -57,13 +53,13 @@ data class InventorySlot(val row: Int, val slotInRow: Int) : Comparable= 0) realRow - 1 else 0 return ((rowsUnder * inventoryDimensions.width) + slotInRow) - 1 } fun isInDimension(inventoryDimensions: InventoryDimensions) = - (1..inventoryDimensions.width).contains(slotInRow) && (1..inventoryDimensions.heigth).contains(row) + (1..inventoryDimensions.width).contains(slotInRow) && (1..inventoryDimensions.height).contains(row) fun add(offsetHorizontally: Int, offsetVertically: Int) = InventorySlot( row + offsetVertically, @@ -182,7 +178,7 @@ class InventoryColumnSlots internal constructor( ) : InventorySlotCompound { override fun withInvType(invType: InventoryType) = HashSet().apply { - for (row in 1..invType.dimensions.heigth) + for (row in 1..invType.dimensions.height) this += InventorySlot(row, column) } @@ -199,9 +195,9 @@ class InventoryBorderSlots internal constructor( for (currentPadding in 0 until padding) { for (slotInRow in 1 + currentPadding..dimensions.width - currentPadding) { this += InventorySlot(1, slotInRow) - this += InventorySlot(dimensions.heigth, slotInRow) + this += InventorySlot(dimensions.height, slotInRow) } - for (row in 2 + currentPadding until dimensions.heigth - currentPadding) { + for (row in 2 + currentPadding until dimensions.height - currentPadding) { this += InventorySlot(row, 1) this += InventorySlot(row, dimensions.width) } @@ -224,8 +220,8 @@ class InventoryCornerSlots internal constructor( if (ifBottomLeft) this += InventorySlot(1, 1) if (ifBottomRight) this += InventorySlot(1, dimensions.width) - if (ifTopLeft) this += InventorySlot(dimensions.heigth, 1) - if (ifTopRight) this += InventorySlot(dimensions.heigth, dimensions.width) + if (ifTopLeft) this += InventorySlot(dimensions.height, 1) + if (ifTopRight) this += InventorySlot(dimensions.height, dimensions.width) } diff --git a/src/main/kotlin/net/axay/kspigot/inventory/InventoryType.kt b/src/main/kotlin/net/axay/kspigot/inventory/InventoryType.kt index 8510a25d..8204120f 100644 --- a/src/main/kotlin/net/axay/kspigot/inventory/InventoryType.kt +++ b/src/main/kotlin/net/axay/kspigot/inventory/InventoryType.kt @@ -12,8 +12,6 @@ class InventoryType( val bukkitType: InventoryType? = null ) { - private val size = dimensions.width * dimensions.heigth - companion object { val ONE_BY_NINE = InventoryType(InventoryDimensions(9, 1)) @@ -33,7 +31,7 @@ class InventoryType( val realTitle = title ?: "" return when { bukkitType != null -> Bukkit.createInventory(holder, bukkitType, realTitle) - else -> Bukkit.createInventory(holder, size, realTitle) + else -> Bukkit.createInventory(holder, dimensions.slotAmount, realTitle) } } diff --git a/src/main/kotlin/net/axay/kspigot/inventory/elements/InventoryGUIButton.kt b/src/main/kotlin/net/axay/kspigot/inventory/elements/InventoryGUIButton.kt index 903c14f2..f8015f3d 100644 --- a/src/main/kotlin/net/axay/kspigot/inventory/elements/InventoryGUIButton.kt +++ b/src/main/kotlin/net/axay/kspigot/inventory/elements/InventoryGUIButton.kt @@ -1,14 +1,14 @@ package net.axay.kspigot.inventory.elements -import net.axay.kspigot.inventory.ForInventory -import net.axay.kspigot.inventory.InventoryGUIClickEvent -import net.axay.kspigot.inventory.InventoryGUIElement -import net.axay.kspigot.inventory.InventoryGUIElementData +import net.axay.kspigot.inventory.* +import org.bukkit.inventory.ItemStack open class InventoryGUIButton( - inventoryGUIElementData: InventoryGUIElementData, + private val icon: ItemStack, val action: (InventoryGUIClickEvent) -> Unit, -) : InventoryGUIElement(inventoryGUIElementData) { +) : InventoryGUIElement() { + + override fun getItemStack(slot: Int) = icon override fun onClickElement(clickEvent: InventoryGUIClickEvent) { clickEvent.bukkitEvent.isCancelled = true diff --git a/src/main/kotlin/net/axay/kspigot/inventory/elements/InventoryGUIButtonInventoryChange.kt b/src/main/kotlin/net/axay/kspigot/inventory/elements/InventoryGUIButtonInventoryChange.kt index 5180ceb8..a41c2713 100644 --- a/src/main/kotlin/net/axay/kspigot/inventory/elements/InventoryGUIButtonInventoryChange.kt +++ b/src/main/kotlin/net/axay/kspigot/inventory/elements/InventoryGUIButtonInventoryChange.kt @@ -1,13 +1,14 @@ package net.axay.kspigot.inventory.elements import net.axay.kspigot.inventory.* +import org.bukkit.inventory.ItemStack class InventoryGUIButtonInventoryChange( - inventoryGUIElementData: InventoryGUIElementData, + icon: ItemStack, changeToGUICallback: () -> InventoryGUI<*>, changeToPageInt: Int?, onChange: ((InventoryGUIClickEvent) -> Unit)? -) : InventoryGUIButton(inventoryGUIElementData, { +) : InventoryGUIButton(icon, { val changeToGUI = changeToGUICallback.invoke() diff --git a/src/main/kotlin/net/axay/kspigot/inventory/elements/InventoryGUIButtonPageChange.kt b/src/main/kotlin/net/axay/kspigot/inventory/elements/InventoryGUIButtonPageChange.kt index 19fad581..ab63f162 100644 --- a/src/main/kotlin/net/axay/kspigot/inventory/elements/InventoryGUIButtonPageChange.kt +++ b/src/main/kotlin/net/axay/kspigot/inventory/elements/InventoryGUIButtonPageChange.kt @@ -1,12 +1,13 @@ package net.axay.kspigot.inventory.elements import net.axay.kspigot.inventory.* +import org.bukkit.inventory.ItemStack class InventoryGUIButtonPageChange( - inventoryGUIElementData: InventoryGUIElementData, + icon: ItemStack, calculator: InventoryGUIPageChangeCalculator, onChange: ((InventoryGUIClickEvent) -> Unit)? -) : InventoryGUIButton(inventoryGUIElementData, { +) : InventoryGUIButton(icon, { val currentPage = it.gui.currentPage val newPage = it.gui.getPage(calculator.calculateNewPage(it.gui.currentPageInt, it.gui.data.pages.keys)) diff --git a/src/main/kotlin/net/axay/kspigot/inventory/elements/InventoryGUIPlaceholder.kt b/src/main/kotlin/net/axay/kspigot/inventory/elements/InventoryGUIPlaceholder.kt index 004c6133..bd93aa64 100644 --- a/src/main/kotlin/net/axay/kspigot/inventory/elements/InventoryGUIPlaceholder.kt +++ b/src/main/kotlin/net/axay/kspigot/inventory/elements/InventoryGUIPlaceholder.kt @@ -1,13 +1,13 @@ package net.axay.kspigot.inventory.elements -import net.axay.kspigot.inventory.ForInventory -import net.axay.kspigot.inventory.InventoryGUIClickEvent -import net.axay.kspigot.inventory.InventoryGUIElement -import net.axay.kspigot.inventory.InventoryGUIElementData +import net.axay.kspigot.inventory.* +import org.bukkit.inventory.ItemStack class InventoryGUIPlaceholder( - inventoryGUIElementData: InventoryGUIElementData -) : InventoryGUIElement(inventoryGUIElementData) { + private val icon: ItemStack +) : InventoryGUIElement() { + + override fun getItemStack(slot: Int) = icon override fun onClickElement(clickEvent: InventoryGUIClickEvent) { clickEvent.bukkitEvent.isCancelled = true diff --git a/src/main/kotlin/net/axay/kspigot/inventory/elements/InventoryGUISpaceCompound.kt b/src/main/kotlin/net/axay/kspigot/inventory/elements/InventoryGUISpaceCompound.kt new file mode 100644 index 00000000..efa3e645 --- /dev/null +++ b/src/main/kotlin/net/axay/kspigot/inventory/elements/InventoryGUISpaceCompound.kt @@ -0,0 +1,114 @@ +@file:Suppress("MemberVisibilityCanBePrivate", "unused") + +package net.axay.kspigot.inventory.elements + +import net.axay.kspigot.inventory.* +import org.bukkit.Material +import org.bukkit.inventory.ItemStack + +class InventoryGUISpaceCompoundElement( + private val compound: InventoryGUISpaceCompound +) : InventoryGUIElement() { + + override fun getItemStack(slot: Int) = compound.getItemStack(slot) + + override fun onClickElement(clickEvent: InventoryGUIClickEvent) { + compound.onClickElement(clickEvent) + } + + override fun startUsing(gui: InventoryGUI<*>) = compound.registerGUI(gui) + + override fun stopUsing(gui: InventoryGUI<*>) = compound.unregisterGUI(gui) + +} + +class InventoryGUISpaceCompound( + private val invType: InventoryType, + private val iconGenerator: (E) -> ItemStack, + private val onClick: (InventoryGUIClickEvent, E) -> Unit +) { + + private val content = ArrayList() + + private val realInternalSlots = ArrayList() + + private val currentInternalSlots: List get() { + + val result = ArrayList(realInternalSlots) + + var more = 1 + while (content.size > result.size) { + result += realInternalSlots.mapTo(ArrayList()) { it + (more * invType.dimensions.slotAmount) } + more++ + } + + return result + + } + + private var scrolledLines: Int = 0 + + private var contentSort: () -> Unit = { } + + private val registeredGUIs = HashSet>() + + private fun translateSlot(slot: Int) = (scrolledLines * invType.dimensions.width) + slot + + private fun contentAtSlot(slot: Int) = content.getOrNull( + realInternalSlots.indexOf(translateSlot(slot)) + ) + + internal fun getItemStack(slot: Int): ItemStack { + return contentAtSlot(slot)?.let { return@let iconGenerator.invoke(it) } + ?: ItemStack(Material.AIR) + } + + internal fun onClickElement(clickEvent: InventoryGUIClickEvent) { + val element = contentAtSlot(clickEvent.bukkitEvent.slot) ?: return + onClick.invoke(clickEvent, element) + } + + internal fun addSlots(slots: InventorySlotCompound) { + slots.realSlotsWithInvType(invType).forEach { + if (!realInternalSlots.contains(it)) + realInternalSlots.add(it) + } + realInternalSlots.sort() + } + + internal fun registerGUI(gui: InventoryGUI<*>) { + registeredGUIs += gui + } + + internal fun unregisterGUI(gui: InventoryGUI<*>) { + registeredGUIs -= gui + } + + /** + * Defines the sort behaviour which gets applied to the content + * automatically. + */ + fun > sortContentBy(reverse: Boolean = false, selector: (E) -> R?) { + contentSort = { + if (!reverse) content.sortBy(selector) else content.sortByDescending(selector) + } + contentSort.invoke() + } + + /** + * Adds a new element to the compound. + */ + fun addContent(element: E) { + addContent(listOf(element)) + } + + /** + * Adds new elements to the compound. + */ + fun addContent(elements: Collection) { + content += elements + contentSort.invoke() + registeredGUIs.forEach { it.reloadCurrentPage() } + } + +} \ No newline at end of file diff --git a/src/main/kotlin/net/axay/kspigot/main/KSpigot.kt b/src/main/kotlin/net/axay/kspigot/main/KSpigot.kt index 3ee09216..6c694ac6 100644 --- a/src/main/kotlin/net/axay/kspigot/main/KSpigot.kt +++ b/src/main/kotlin/net/axay/kspigot/main/KSpigot.kt @@ -1,7 +1,7 @@ package net.axay.kspigot.main import net.axay.kspigot.inventory.InventoryGUIHolder -import net.axay.kspigot.languageextensions.closeIfInitialized +import net.axay.kspigot.languageextensions.kotlinextensions.closeIfInitialized import net.axay.kspigot.runnables.KRunnableHolder import org.bukkit.plugin.java.JavaPlugin diff --git a/src/main/kotlin/net/axay/kspigot/particles/KSpigotParticles.kt b/src/main/kotlin/net/axay/kspigot/particles/KSpigotParticles.kt index 68e3d2d0..5e28adbf 100644 --- a/src/main/kotlin/net/axay/kspigot/particles/KSpigotParticles.kt +++ b/src/main/kotlin/net/axay/kspigot/particles/KSpigotParticles.kt @@ -1,7 +1,7 @@ package net.axay.kspigot.particles import net.axay.kspigot.extensions.bukkit.worldOrException -import net.axay.kspigot.languageextensions.applyIfNotNull +import net.axay.kspigot.languageextensions.kotlinextensions.applyIfNotNull import org.bukkit.Location import org.bukkit.Particle import org.bukkit.entity.Player diff --git a/src/main/kotlin/net/axay/kspigot/sound/KSpigotSound.kt b/src/main/kotlin/net/axay/kspigot/sound/KSpigotSound.kt index fd5351a3..70300b7b 100644 --- a/src/main/kotlin/net/axay/kspigot/sound/KSpigotSound.kt +++ b/src/main/kotlin/net/axay/kspigot/sound/KSpigotSound.kt @@ -1,7 +1,7 @@ package net.axay.kspigot.sound import net.axay.kspigot.extensions.bukkit.worldOrException -import net.axay.kspigot.languageextensions.applyIfNotNull +import net.axay.kspigot.languageextensions.kotlinextensions.applyIfNotNull import org.bukkit.Location import org.bukkit.Sound import org.bukkit.SoundCategory