diff --git a/src/main/kotlin/net/axay/kspigot/inventory/InventoryGUI.kt b/src/main/kotlin/net/axay/kspigot/inventory/InventoryGUI.kt new file mode 100644 index 00000000..012bd73b --- /dev/null +++ b/src/main/kotlin/net/axay/kspigot/inventory/InventoryGUI.kt @@ -0,0 +1,166 @@ +@file:Suppress("MemberVisibilityCanBePrivate") + +package net.axay.kspigot.inventory + +import net.axay.kspigot.event.listen +import net.axay.kspigot.event.register +import net.axay.kspigot.main.KSpigot +import org.bukkit.entity.HumanEntity +import org.bukkit.event.EventHandler +import org.bukkit.event.Listener +import org.bukkit.event.inventory.InventoryClickEvent +import org.bukkit.event.inventory.InventoryInteractEvent +import org.bukkit.inventory.Inventory +import org.bukkit.inventory.InventoryView + +// EXTENSIONS + +fun HumanEntity.openGUI(gui: InventoryGUI, page: Int = 1): InventoryView? { + closeInventory() + gui.loadPage(page) + return openInventory(gui.bukkitInventory) +} + +// GUI HOLDER + +class InventoryGUIHolder(kSpigot: KSpigot) : AutoCloseable { + + private val registered = HashSet() + + fun register(inventoryGUI: InventoryGUI) { + registered += inventoryGUI + } + + fun unregister(inventoryGUI: InventoryGUI) { + registered -= inventoryGUI + } + + init { + + object : Listener { + @EventHandler + private fun onInteract(event: InventoryInteractEvent) { + println("interact geht hier") + } + }.register(kSpigot) + + kSpigot.listen { + + val inv = registered.find { search -> search.isThisInv(it.inventory) } ?: return@listen + val invPage = inv.currentPage ?: return@listen + + 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 + */ + +class InventoryGUIData( + val plugin: KSpigot, + val inventoryGUIType: InventoryGUIType<*>, + val title: String?, + val pages: Map +) + +abstract class InventoryGUI( + val data: InventoryGUIData +) { + + var currentPage: Int? = null; protected set + + abstract val bukkitInventory: Inventory + + abstract fun loadPage(page: Int, offsetHorizontally: Int = 0, offsetVertically: Int = 0) + + abstract fun isThisInv(inventory: Inventory): Boolean + + fun register() = data.plugin.inventoryGUIHolder.register(this) + fun unregister() = data.plugin.inventoryGUIHolder.unregister(this) + +} + +// Inventory GUI implementations + +class InventoryGUIShared( + inventoryGUIData: InventoryGUIData +) : InventoryGUI(inventoryGUIData) { + + override val bukkitInventory by lazy { data.inventoryGUIType.createBukkitInv(null, data.title) } + + override fun isThisInv(inventory: Inventory) = inventory == bukkitInventory + + override fun loadPage(page: Int, offsetHorizontally: Int, offsetVertically: Int) { + + fun ifOffset(): Boolean = offsetHorizontally != 0 || offsetVertically != 0 + + currentPage = page + + data.pages[page]?.slots?.let { slots -> + + val dimensions = data.inventoryGUIType.dimensions + + if (ifOffset()) { + dimensions.invSlots.forEach { + dimensions.invSlotsWithRealSlots[it.add(offsetHorizontally, offsetVertically)]?.let { slotToClear -> + if (dimensions.realSlots.contains(slotToClear)) + bukkitInventory.clear(slotToClear) + } + } + } else { + bukkitInventory.clear() + } + + slots.forEach { + 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.inventoryGUIElementData.itemStack) + } + } else { + bukkitInventory.setItem(it.key, slot.inventoryGUIElementData.itemStack) + } + + } + + } + + } + + } + +} + +class InventoryGUIPage( + val slots: Map, + transitionTo: InventoryGUIPageChangeEffect?, + transitionFrom: InventoryGUIPageChangeEffect? +) { + val pageChangerTo = transitionTo?.let { InventoryGUIPageChanger(it) } + val pageChangerFrom = transitionFrom?.let { InventoryGUIPageChanger(it) } +} \ 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 new file mode 100644 index 00000000..aea37bf4 --- /dev/null +++ b/src/main/kotlin/net/axay/kspigot/inventory/InventoryGUIBuilder.kt @@ -0,0 +1,108 @@ +@file:Suppress("MemberVisibilityCanBePrivate", "unused") + +package net.axay.kspigot.inventory + +import net.axay.kspigot.main.KSpigot +import org.bukkit.inventory.ItemStack + +inline fun KSpigot.inventoryGUI( + type: InventoryGUIType, + builder: InventoryGUIBuilder.() -> Unit, +) = InventoryGUIBuilder(this, type).apply(builder).build() + +class InventoryGUIBuilder( + private val kSpigot: KSpigot, + val type: InventoryGUIType +) { + + var title: String = "" + + private val guiSlots = HashMap() + + /** + * + */ + fun page(page: Int, builder: InventoryGUIPageBuilder.() -> Unit) { + guiSlots[page] = InventoryGUIPageBuilder(type, page).apply(builder).build() + } + + fun build() = InventoryGUIShared(InventoryGUIData(kSpigot, type, title, guiSlots)).apply { register() } + +} + +class InventoryGUIPageBuilder( + val type: InventoryGUIType, + val page: Int +) { + + private val guiSlots = HashMap() + + var transitionTo: InventoryGUIPageChangeEffect? = null + var transitionFrom: InventoryGUIPageChangeEffect? = null + + /** + * A button is an item protected from any player + * actions. If clicked, the specified [onClick] + * function is invoked. + */ + fun button(slots: InventorySlotCompound, itemStack: ItemStack, onClick: (InventoryGUIClickEvent) -> Unit) + = slots(slots, InventoryGUIButton(InventoryGUIElementData(itemStack), onClick)) + + /** + * An item protected from any player actions. + * This is not a button. + */ + fun placeholder(slots: InventorySlotCompound, itemStack: ItemStack) + = slots(slots, InventoryGUIPlaceholder(InventoryGUIElementData(itemStack))) + + /** + * A free slot does not block any player actions. + * The player can put items in this slot or take + * items out of it. + */ + fun freeSlot(slots: InventorySlotCompound) + = slots(slots, InventoryGUIFreeSlot()) + + /** + * This is a button which loads the specified + * [toPage] if clicked. + */ + fun pageChanger(slots: InventorySlotCompound, itemStack: ItemStack, toPage: Int, onChange: ((InventoryGUIClickEvent) -> Unit)? = null) + = slots(slots, InventoryGUIButtonPageChange( + InventoryGUIElementData(itemStack), + InventoryGUIPageChangeCalculator.InventoryGUIConsistentPageCalculator(toPage), + onChange + )) + + /** + * This button always tries to find the previous + * page if clicked, and if a previous page + * exists it is loaded. + */ + fun previousPage(slots: InventorySlotCompound, itemStack: ItemStack, onChange: ((InventoryGUIClickEvent) -> Unit)? = null) + = slots(slots, InventoryGUIButtonPageChange( + InventoryGUIElementData(itemStack), + InventoryGUIPageChangeCalculator.InventoryGUIPreviousPageCalculator, + onChange + )) + + /** + * This button always tries to find the next + * page if clicked, and if a next page + * exists it is loaded. + */ + fun nextPage(slots: InventorySlotCompound, itemStack: ItemStack, onChange: ((InventoryGUIClickEvent) -> Unit)? = null) + = slots(slots, InventoryGUIButtonPageChange( + InventoryGUIElementData(itemStack), + InventoryGUIPageChangeCalculator.InventoryGUINextPageCalculator, + onChange + )) + + private fun slots(slots: InventorySlotCompound, element: InventoryGUISlot) + = slots.withGUIType(type).forEach { curSlot -> + curSlot.realSlotIn(type.dimensions)?.let { guiSlots[it] = element } + } + + fun build() = InventoryGUIPage(guiSlots, transitionTo, transitionFrom) + +} \ 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 new file mode 100644 index 00000000..7fedfd27 --- /dev/null +++ b/src/main/kotlin/net/axay/kspigot/inventory/InventoryGUIElements.kt @@ -0,0 +1,71 @@ +package net.axay.kspigot.inventory + +import org.bukkit.inventory.ItemStack + +interface InventoryGUISlot { + fun onClick(clickEvent: InventoryGUIClickEvent) +} + +// ELEMENT + +class InventoryGUIElementData( + val itemStack: ItemStack +) + +abstract class InventoryGUIElement( + val inventoryGUIElementData: InventoryGUIElementData +) : InventoryGUISlot + +// Element implementations + +open class InventoryGUIButton( + inventoryGUIElementData: InventoryGUIElementData, + val action: (InventoryGUIClickEvent) -> Unit, +) : InventoryGUIElement(inventoryGUIElementData) { + + override fun onClick(clickEvent: InventoryGUIClickEvent) { + clickEvent.bukkitEvent.isCancelled = true + action(clickEvent) + } + +} + +class InventoryGUIPlaceholder( + inventoryGUIElementData: InventoryGUIElementData +) : InventoryGUIElement(inventoryGUIElementData) { + + override fun onClick(clickEvent: InventoryGUIClickEvent) { + clickEvent.bukkitEvent.isCancelled = true + } + +} + +class InventoryGUIButtonPageChange( + inventoryGUIElementData: InventoryGUIElementData, + calculator: InventoryGUIPageChangeCalculator, + onChange: ((InventoryGUIClickEvent) -> Unit)? +) + : InventoryGUIButton(inventoryGUIElementData, { + it.gui.currentPage?.let { currentPageInt -> + + val newPageInt = calculator.calculateNewPage(currentPageInt, it.gui.data.pages.keys) + if (newPageInt != null) { + + onChange?.invoke(it) + + val pageChanger + = (it.gui.data.pages[newPageInt]?.pageChangerTo ?: it.gui.data.pages[currentPageInt]?.pageChangerFrom) + ?: InventoryGUIPageChanger(InventoryGUIPageChangeEffect.INSTANT) + + pageChanger.changePage(it.gui, currentPageInt, newPageInt) + + } + + } + }) + +// FREE SLOT + +class InventoryGUIFreeSlot : InventoryGUISlot { + override fun onClick(clickEvent: InventoryGUIClickEvent) { /* do nothing */ } +} \ 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 new file mode 100644 index 00000000..1d2d0a5f --- /dev/null +++ b/src/main/kotlin/net/axay/kspigot/inventory/InventoryGUIPageChange.kt @@ -0,0 +1,68 @@ +package net.axay.kspigot.inventory + +import net.axay.kspigot.runnables.task + +abstract class InventoryGUIPageChangeCalculator { + + abstract fun calculateNewPage(currentPage: Int, pages: Collection): Int? + + object InventoryGUIPreviousPageCalculator : InventoryGUIPageChangeCalculator() { + override fun calculateNewPage(currentPage: Int, pages: Collection) = pages.sortedDescending().find { it < currentPage } + } + + object InventoryGUINextPageCalculator : InventoryGUIPageChangeCalculator() { + override fun calculateNewPage(currentPage: Int, pages: Collection) = pages.sorted().find { it > currentPage } + } + + class InventoryGUIConsistentPageCalculator(private val toPage: Int) : InventoryGUIPageChangeCalculator() { + override fun calculateNewPage(currentPage: Int, pages: Collection) = toPage + } + +} + +enum class InventoryGUIPageChangeEffect { + INSTANT, SLIDE_HORIZONTALLY +} + +class InventoryGUIPageChanger(private val effect: InventoryGUIPageChangeEffect) { + + fun changePage(gui: InventoryGUI, fromPage: Int, toPage: Int) { + when (effect) { + + InventoryGUIPageChangeEffect.SLIDE_HORIZONTALLY -> { + + val width = gui.data.inventoryGUIType.dimensions.width + + val ifInverted = fromPage >= toPage + + var currentOffset = 1 + gui.data.plugin.task( + sync = true, + period = 1, + howOften = width.toLong() + ) { + + if (ifInverted) { + gui.loadPage(fromPage, currentOffset) + gui.loadPage(toPage, - (width - currentOffset)) + } else { + gui.loadPage(fromPage, -currentOffset) + gui.loadPage(toPage, width - currentOffset) + } + + currentOffset++ + + } + + } + + InventoryGUIPageChangeEffect.INSTANT -> { + + gui.loadPage(toPage) + + } + + } + } + +} \ No newline at end of file diff --git a/src/main/kotlin/net/axay/kspigot/inventory/InventoryGUISlots.kt b/src/main/kotlin/net/axay/kspigot/inventory/InventoryGUISlots.kt new file mode 100644 index 00000000..7cc8bf1a --- /dev/null +++ b/src/main/kotlin/net/axay/kspigot/inventory/InventoryGUISlots.kt @@ -0,0 +1,236 @@ +@file:Suppress("unused", "MemberVisibilityCanBePrivate") + +package net.axay.kspigot.inventory + +// INVENTORY + +data class InventoryDimensions(val width: Int, val heigth: Int) { + + val invSlots by lazy { + ArrayList().apply { + (1 .. heigth).forEach { row -> + (1 .. width).forEach { slotInRow -> + this += InventorySlot(row, slotInRow) + } } + } + } + + 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 -> + curSlot.realSlotIn(this@InventoryDimensions)?.let { this[curSlot] = it } + } + } + } + +} + +// SLOTS + +data class InventorySlot(val row: Int, val slotInRow: Int) : Comparable { + + companion object { + fun fromRealSlot(realSlot: Int, dimensions: InventoryDimensions) + = dimensions.invSlotsWithRealSlots.toList().find { it.second == realSlot }?.first + } + + override fun compareTo(other: InventorySlot) = when { + row > other.row -> 1 + row < other.row -> -1 + else -> when { + slotInRow > other.slotInRow -> 1 + slotInRow < other.slotInRow -> -1 + else -> 0 + } + } + + fun realSlotIn(inventoryDimensions: InventoryDimensions): Int? { + if (!isInDimension(inventoryDimensions)) return null + val realRow = inventoryDimensions.heigth - (row - 1) + val rowsUnder = if (realRow - 1 >= 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) + + fun add(offsetHorizontally: Int, offsetVertically: Int) = InventorySlot( + row + offsetVertically, + slotInRow + offsetHorizontally + ) + +} + +interface InventorySlotCompound { + fun withGUIType(invType: InventoryGUIType): Collection +} + +open class SingleInventorySlot(val inventorySlot: InventorySlot) + : InventorySlotCompound { + + constructor(row: Int, slotInRow: Int) : this(InventorySlot(row, slotInRow)) + + private val slotAsList = listOf(inventorySlot) + + override fun withGUIType(invType: InventoryGUIType) = slotAsList + +} + +enum class InventorySlotRangeType { LINEAR, RECTANGLE } + +class InventorySlotRange ( + + startSlot: SingleInventorySlot, + endSlot: SingleInventorySlot, + + private val type: InventorySlotRangeType + +) : InventorySlotCompound, ClosedRange { + + override val start: InventorySlot + override val endInclusive: InventorySlot + + init { + if (startSlot.inventorySlot <= endSlot.inventorySlot) { + start = startSlot.inventorySlot + endInclusive = endSlot.inventorySlot + } else { + start = endSlot.inventorySlot + endInclusive = startSlot.inventorySlot + } + } + + override fun withGUIType(invType: InventoryGUIType) + = LinkedHashSet().apply { + when (type) { + + InventorySlotRangeType.RECTANGLE -> { + // all possible combinations between the two slots + // -> form a rectangle + for (row in start.row .. endInclusive.row) + for (slotInRow in start.slotInRow .. endInclusive.slotInRow) + this += InventorySlot(row, slotInRow) + } + + InventorySlotRangeType.LINEAR -> { + if (endInclusive.row > start.row) { + // from start --->| to end of row + for (slotInRow in start.slotInRow .. invType.dimensions.width) + this += InventorySlot(start.row, slotInRow) + // all rows in between + if (endInclusive.row > start.row + 1) + for (row in start.row + 1 until endInclusive.row) + for (slotInRow in 1 .. invType.dimensions.width) + this += InventorySlot(row, slotInRow) + // from start of row |----> to endInclusive + for (slotInRow in 1 .. endInclusive.slotInRow) + this += InventorySlot(endInclusive.row, slotInRow) + } else if (endInclusive.row == start.row) { + // from start ---> to endInclusive in the same row + for (slotInRow in start.slotInRow .. endInclusive.slotInRow) + this += InventorySlot(start.row, slotInRow) + } + } + + } + } + +} + +// SLOT RANGE OPERATOR FUNCTIONS + +infix fun SingleInventorySlot.linTo(slot: SingleInventorySlot) + = InventorySlotRange(this, slot, InventorySlotRangeType.LINEAR) + +infix fun SingleInventorySlot.rectTo(slot: SingleInventorySlot) + = InventorySlotRange(this, slot, InventorySlotRangeType.RECTANGLE) + +// SLOT TYPE SAFETY + +// ROWS +interface ForRowOne : ForInventoryOneByNine, ForInventoryTwoByNine, ForInventoryThreeByNine, ForInventoryFourByNine, ForInventoryFiveByNine, ForInventorySixByNine +interface ForRowTwo : ForInventoryTwoByNine, ForInventoryThreeByNine, ForInventoryFourByNine, ForInventoryFiveByNine, ForInventorySixByNine +interface ForRowThree : ForInventoryThreeByNine, ForInventoryFourByNine, ForInventoryFiveByNine, ForInventorySixByNine +interface ForRowFour : ForInventoryFourByNine, ForInventoryFiveByNine, ForInventorySixByNine +interface ForRowFive : ForInventoryFiveByNine, ForInventorySixByNine +interface ForRowSix : ForInventorySixByNine + +// EDGE CASES: +// ROW ONE +interface ForRowOneSlotOneToThree : ForRowOne, ForInventoryOneByFive, ForInventoryThreeByThree +interface ForRowOneSlotFourToFive : ForRowOne, ForInventoryOneByFive +// ROW TWO +interface ForRowTwoSlotOneToThree : ForRowTwo, ForInventoryThreeByThree +// ROW THREE +interface ForRowThreeSlotOneToThree : ForRowThree, ForInventoryThreeByThree + +object Slots { + // ROW ONE + val RowOneSlotOne = SingleInventorySlot(1, 1) + val RowOneSlotTwo = SingleInventorySlot(1, 2) + val RowOneSlotThree = SingleInventorySlot(1, 3) + val RowOneSlotFour = SingleInventorySlot(1, 4) + val RowOneSlotFive = SingleInventorySlot(1, 5) + val RowOneSlotSix = SingleInventorySlot(1, 6) + val RowOneSlotSeven = SingleInventorySlot(1, 7) + val RowOneSlotEight = SingleInventorySlot(1, 8) + val RowOneSlotNine = SingleInventorySlot(1, 9) + // ROW TWO + val RowTwoSlotOne = SingleInventorySlot(2, 1) + val RowTwoSlotTwo = SingleInventorySlot(2, 2) + val RowTwoSlotThree = SingleInventorySlot(2, 3) + val RowTwoSlotFour = SingleInventorySlot(2, 4) + val RowTwoSlotFive = SingleInventorySlot(2, 5) + val RowTwoSlotSix = SingleInventorySlot(2, 6) + val RowTwoSlotSeven = SingleInventorySlot(2, 7) + val RowTwoSlotEight = SingleInventorySlot(2, 8) + val RowTwoSlotNine = SingleInventorySlot(2, 9) + // ROW THREE + val RowThreeSlotOne = SingleInventorySlot(3, 1) + val RowThreeSlotTwo = SingleInventorySlot(3, 2) + val RowThreeSlotThree = SingleInventorySlot(3, 3) + val RowThreeSlotFour = SingleInventorySlot(3, 4) + val RowThreeSlotFive = SingleInventorySlot(3, 5) + val RowThreeSlotSix = SingleInventorySlot(3, 6) + val RowThreeSlotSeven = SingleInventorySlot(3, 7) + val RowThreeSlotEight = SingleInventorySlot(3, 8) + val RowThreeSlotNine = SingleInventorySlot(3, 9) + // ROW FOUR + val RowFourSlotOne = SingleInventorySlot(4, 1) + val RowFourSlotTwo = SingleInventorySlot(4, 2) + val RowFourSlotThree = SingleInventorySlot(4, 3) + val RowFourSlotFour = SingleInventorySlot(4, 4) + val RowFourSlotFive = SingleInventorySlot(4, 5) + val RowFourSlotSix = SingleInventorySlot(4, 6) + val RowFourSlotSeven = SingleInventorySlot(4, 7) + val RowFourSlotEight = SingleInventorySlot(4, 8) + val RowFourSlotNine = SingleInventorySlot(4, 9) + // ROW FIVE + val RowFiveSlotOne = SingleInventorySlot(5, 1) + val RowFiveSlotTwo = SingleInventorySlot(5, 2) + val RowFiveSlotThree = SingleInventorySlot(5, 3) + val RowFiveSlotFour = SingleInventorySlot(5, 4) + val RowFiveSlotFive = SingleInventorySlot(5, 5) + val RowFiveSlotSix = SingleInventorySlot(5, 6) + val RowFiveSlotSeven = SingleInventorySlot(5, 7) + val RowFiveSlotEight = SingleInventorySlot(5, 8) + val RowFiveSlotNine = SingleInventorySlot(5, 9) + // ROW SIX + val RowSixSlotOne = SingleInventorySlot(6, 1) + val RowSixSlotTwo = SingleInventorySlot(6, 2) + val RowSixSlotThree = SingleInventorySlot(6, 3) + val RowSixSlotFour = SingleInventorySlot(6, 4) + val RowSixSlotFive = SingleInventorySlot(6, 5) + val RowSixSlotSix = SingleInventorySlot(6, 6) + val RowSixSlotSeven = SingleInventorySlot(6, 7) + val RowSixSlotEight = SingleInventorySlot(6, 8) + val RowSixSlotNine = SingleInventorySlot(6, 9) +} \ No newline at end of file diff --git a/src/main/kotlin/net/axay/kspigot/inventory/InventoryGUIType.kt b/src/main/kotlin/net/axay/kspigot/inventory/InventoryGUIType.kt new file mode 100644 index 00000000..3c3bd468 --- /dev/null +++ b/src/main/kotlin/net/axay/kspigot/inventory/InventoryGUIType.kt @@ -0,0 +1,56 @@ +@file:Suppress("MemberVisibilityCanBePrivate", "CanBeParameter") + +package net.axay.kspigot.inventory + +import org.bukkit.Bukkit +import org.bukkit.event.inventory.InventoryType +import org.bukkit.inventory.Inventory +import org.bukkit.inventory.InventoryHolder + +class InventoryGUIType( + val dimensions: InventoryDimensions, + val bukkitType: InventoryType? = null +) { + + private val size = dimensions.width * dimensions.heigth + + companion object { + + val ONE_BY_NINE = InventoryGUIType(InventoryDimensions(9, 1)) + val TWO_BY_NINE = InventoryGUIType(InventoryDimensions(9, 2)) + val THREE_BY_NINE = InventoryGUIType(InventoryDimensions(9, 3)) + val FOUR_BY_NINE = InventoryGUIType(InventoryDimensions(9, 4)) + val FIVE_BY_NINE = InventoryGUIType(InventoryDimensions(9, 5)) + val SIX_BY_NINE = InventoryGUIType(InventoryDimensions(9, 6)) + val ONE_BY_FIVE = InventoryGUIType(InventoryDimensions(5, 1), bukkitType = InventoryType.HOPPER) + val THREE_BY_THREE = InventoryGUIType(InventoryDimensions(3, 3), bukkitType = InventoryType.DROPPER) + + } + + 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, size, realTitle) + } + } + +} + +// INVENTORY TYPE SAFETY + +interface ForInventory + +interface ForInventoryOneByNine : ForInventory +interface ForInventoryTwoByNine : ForInventory +interface ForInventoryThreeByNine : ForInventory +interface ForInventoryFourByNine : ForInventory +interface ForInventoryFiveByNine : ForInventory +interface ForInventorySixByNine : ForInventory +interface ForInventoryThreeByThree : ForInventory +interface ForInventoryOneByFive : ForInventory + +interface ForEveryInventory + : ForInventoryOneByNine, ForInventoryTwoByNine, ForInventoryThreeByNine, + ForInventoryFourByNine, ForInventoryFiveByNine, ForInventorySixByNine, + ForInventoryThreeByThree, ForInventoryOneByFive \ 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 8fb6df78..d2d9bc9e 100644 --- a/src/main/kotlin/net/axay/kspigot/main/KSpigot.kt +++ b/src/main/kotlin/net/axay/kspigot/main/KSpigot.kt @@ -1,5 +1,6 @@ package net.axay.kspigot.main +import net.axay.kspigot.inventory.InventoryGUIHolder import net.axay.kspigot.kotlinextensions.closeIfInitialized import net.axay.kspigot.runnables.KRunnableHolder import org.bukkit.plugin.java.JavaPlugin @@ -21,8 +22,10 @@ abstract class KSpigot : JavaPlugin() { // lazy properties private val kRunnableHolderProperty = lazy { KRunnableHolder() } + private val inventoryGUIHolderProperty = lazy { InventoryGUIHolder(this) } val kRunnableHolder by kRunnableHolderProperty + val inventoryGUIHolder by inventoryGUIHolderProperty /** * Called when the plugin was loaded @@ -53,6 +56,7 @@ abstract class KSpigot : JavaPlugin() { // avoid unnecessary load of lazy properties kRunnableHolderProperty.closeIfInitialized() + inventoryGUIHolderProperty.closeIfInitialized() }