Merge pull request #9 from bluefireoly/guispace

Added GUI Space functionality
This commit is contained in:
Jakob K
2020-10-21 21:05:57 +02:00
committed by GitHub
20 changed files with 342 additions and 168 deletions

View File

@@ -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")
}

View File

@@ -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

View File

@@ -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<InventoryGUI<ForInventory>>()
fun register(inventoryGUI: InventoryGUI<ForInventory>) {
registered.add(inventoryGUI)
}
fun unregister(inventoryGUI: InventoryGUI<ForInventory>) {
registered.remove(inventoryGUI)
}
init {
listen<InventoryClickEvent> {
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<T : ForInventory>(
val bukkitEvent: InventoryClickEvent,
val gui: InventoryGUI<T>
)
/*
* INVENTORY GUI
*/
private const val DEFAULT_PAGE = 1
class InventoryGUIData<T : ForInventory>(
@@ -94,13 +27,25 @@ abstract class InventoryGUI<T : ForInventory>(
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<Int, InventoryGUISlot<*>>,
offsetHorizontally: Int = 0,
offsetVertically: Int = 0
)
/**
* @return True, if the [inventory] belongs to this GUI.
@@ -136,6 +81,14 @@ abstract class InventoryGUI<T : ForInventory>(
*/
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<T : ForInventory>(
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<Int, InventoryGUISlot<*>>,
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<T : ForInventory>(
}
override fun loadPageUnsafe(page: Int, offsetHorizontally: Int, offsetVertically: Int) {
data.pages[page]?.let { loadPageUnsafe(it, offsetHorizontally, offsetVertically) }
}
override operator fun set(slot: InventorySlotCompound<T>, value: ItemStack) {
slot.realSlotsWithInvType(data.inventoryType).forEach {
bukkitInventory.setItem(it, value)
}
}
}
class InventoryGUIPage<T : ForInventory>(
val number: Int,
internal val slots: Map<Int, InventoryGUISlot<T>>,
val transitionTo: PageChangeEffect?,
val transitionFrom: PageChangeEffect?
)
}

View File

@@ -5,13 +5,15 @@ package net.axay.kspigot.inventory
import net.axay.kspigot.inventory.elements.*
import org.bukkit.inventory.ItemStack
fun <T : ForInventory> inventoryGUI(
fun <T : ForInventory> kSpigotGUI(
type: InventoryType<T>,
shared: Boolean = true,
builder: InventoryGUIBuilder<T>.() -> Unit,
) = InventoryGUIBuilder(type).apply(builder).build()
) = InventoryGUIBuilder(type, shared).apply(builder).build()
class InventoryGUIBuilder<T : ForInventory>(
val type: InventoryType<T>
val type: InventoryType<T>,
val shared: Boolean
) {
var title: String = ""
@@ -36,14 +38,17 @@ class InventoryGUIBuilder<T : ForInventory>(
onClickElement = onClick
}
internal fun build() = InventoryGUIShared(
InventoryGUIData(type, title, guiSlots, transitionTo, transitionFrom, onClickElement)
).apply { register() }
internal fun build(): InventoryGUI<T> {
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<T : ForInventory>(
val type: InventoryType<T>,
private val type: InventoryType<T>,
val page: Int
) {
@@ -60,14 +65,14 @@ class InventoryGUIPageBuilder<T : ForInventory>(
* function is invoked.
*/
fun button(slots: InventorySlotCompound<T>, itemStack: ItemStack, onClick: (InventoryGUIClickEvent<T>) -> 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<T>, 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<T : ForInventory>(
onChange: ((InventoryGUIClickEvent<T>) -> Unit)? = null
) = defineSlots(
slots, InventoryGUIButtonPageChange(
InventoryGUIElementData(itemStack),
itemStack,
InventoryGUIPageChangeCalculator.InventoryGUIConsistentPageCalculator(toPage),
onChange
)
@@ -104,7 +109,7 @@ class InventoryGUIPageBuilder<T : ForInventory>(
onChange: ((InventoryGUIClickEvent<T>) -> Unit)? = null
) = defineSlots(
slots, InventoryGUIButtonPageChange(
InventoryGUIElementData(itemStack),
itemStack,
InventoryGUIPageChangeCalculator.InventoryGUIPreviousPageCalculator,
onChange
)
@@ -121,7 +126,7 @@ class InventoryGUIPageBuilder<T : ForInventory>(
onChange: ((InventoryGUIClickEvent<T>) -> Unit)? = null
) = defineSlots(
slots, InventoryGUIButtonPageChange(
InventoryGUIElementData(itemStack),
itemStack,
InventoryGUIPageChangeCalculator.InventoryGUINextPageCalculator,
onChange
)
@@ -139,13 +144,37 @@ class InventoryGUIPageBuilder<T : ForInventory>(
onChange: ((InventoryGUIClickEvent<T>) -> Unit)? = null
) = defineSlots(
slots, InventoryGUIButtonInventoryChange(
InventoryGUIElementData(itemStack),
itemStack,
newGUI,
newPage,
onChange
)
)
/**
* Defines an area where the content of the given compound
* is displayed.
*/
fun <E> compoundSpace(
slots: InventorySlotCompound<T>,
compound: InventoryGUISpaceCompound<T, E>
) {
compound.addSlots(slots)
defineSlots(
slots,
InventoryGUISpaceCompoundElement(compound)
)
}
/**
* Creates a new compound, holding data which can be displayed
* in any compound space.
*/
fun <E> createCompound(
iconGenerator: (E) -> ItemStack,
onClick: (clickEvent: InventoryGUIClickEvent<T>, element: E) -> Unit
) = InventoryGUISpaceCompound(type, iconGenerator, onClick)
private fun defineSlots(slots: InventorySlotCompound<T>, element: InventoryGUISlot<T>) =
slots.withInvType(type).forEach { curSlot ->
curSlot.realSlotIn(type.dimensions)?.let { guiSlots[it] = element }

View File

@@ -0,0 +1,8 @@
package net.axay.kspigot.inventory
import org.bukkit.event.inventory.InventoryClickEvent
class InventoryGUIClickEvent<T : ForInventory>(
val bukkitEvent: InventoryClickEvent,
val gui: InventoryGUI<T>
)

View File

@@ -8,13 +8,9 @@ abstract class InventoryGUISlot<T : ForInventory> {
// ELEMENT
class InventoryGUIElementData(
val itemStack: ItemStack
)
abstract class InventoryGUIElement<T : ForInventory> : InventoryGUISlot<T>() {
abstract class InventoryGUIElement<T : ForInventory>(
val inventoryGUIElementData: InventoryGUIElementData
) : InventoryGUISlot<T>() {
abstract fun getItemStack(slot: Int): ItemStack
final override fun onClick(clickEvent: InventoryGUIClickEvent<T>) {
clickEvent.gui.data.generalOnClick?.invoke(clickEvent)
@@ -23,4 +19,7 @@ abstract class InventoryGUIElement<T : ForInventory>(
protected abstract fun onClickElement(clickEvent: InventoryGUIClickEvent<T>)
internal open fun startUsing(gui: InventoryGUI<*>) { }
internal open fun stopUsing(gui: InventoryGUI<*>) { }
}

View File

@@ -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)
}

View File

@@ -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<InventoryGUI<ForInventory>>()
fun register(inventoryGUI: InventoryGUI<ForInventory>) {
registered.add(inventoryGUI)
}
fun unregister(inventoryGUI: InventoryGUI<ForInventory>) {
registered.remove(inventoryGUI)
}
init {
listen<InventoryClickEvent> {
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()
}
}

View File

@@ -0,0 +1,8 @@
package net.axay.kspigot.inventory
class InventoryGUIPage<T : ForInventory>(
val number: Int,
internal val slots: Map<Int, InventoryGUISlot<T>>,
val transitionTo: PageChangeEffect?,
val transitionFrom: PageChangeEffect?
)

View File

@@ -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) {

View File

@@ -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<InventorySlot>().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<Int>().apply {
invSlots.forEach { curSlot ->
curSlot.realSlotIn(this@InventoryDimensions)?.let { this += it }
}
}
}
val invSlotsWithRealSlots by lazy {
HashMap<InventorySlot, Int>().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<Inventor
fun realSlotIn(inventoryDimensions: InventoryDimensions): Int? {
if (!isInDimension(inventoryDimensions)) return null
val realRow = inventoryDimensions.heigth - (row - 1)
val realRow = inventoryDimensions.height - (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)
(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<T : ForInventory> internal constructor(
) : InventorySlotCompound<T> {
override fun withInvType(invType: InventoryType<T>) = HashSet<InventorySlot>().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<T : ForInventory> 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<T : ForInventory> 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)
}

View File

@@ -12,8 +12,6 @@ class InventoryType<in T : ForInventory>(
val bukkitType: InventoryType? = null
) {
private val size = dimensions.width * dimensions.heigth
companion object {
val ONE_BY_NINE = InventoryType<ForInventoryOneByNine>(InventoryDimensions(9, 1))
@@ -33,7 +31,7 @@ class InventoryType<in T : ForInventory>(
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)
}
}

View File

@@ -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<T : ForInventory>(
inventoryGUIElementData: InventoryGUIElementData,
private val icon: ItemStack,
val action: (InventoryGUIClickEvent<T>) -> Unit,
) : InventoryGUIElement<T>(inventoryGUIElementData) {
) : InventoryGUIElement<T>() {
override fun getItemStack(slot: Int) = icon
override fun onClickElement(clickEvent: InventoryGUIClickEvent<T>) {
clickEvent.bukkitEvent.isCancelled = true

View File

@@ -1,13 +1,14 @@
package net.axay.kspigot.inventory.elements
import net.axay.kspigot.inventory.*
import org.bukkit.inventory.ItemStack
class InventoryGUIButtonInventoryChange<T : ForInventory>(
inventoryGUIElementData: InventoryGUIElementData,
icon: ItemStack,
changeToGUICallback: () -> InventoryGUI<*>,
changeToPageInt: Int?,
onChange: ((InventoryGUIClickEvent<T>) -> Unit)?
) : InventoryGUIButton<T>(inventoryGUIElementData, {
) : InventoryGUIButton<T>(icon, {
val changeToGUI = changeToGUICallback.invoke()

View File

@@ -1,12 +1,13 @@
package net.axay.kspigot.inventory.elements
import net.axay.kspigot.inventory.*
import org.bukkit.inventory.ItemStack
class InventoryGUIButtonPageChange<T : ForInventory>(
inventoryGUIElementData: InventoryGUIElementData,
icon: ItemStack,
calculator: InventoryGUIPageChangeCalculator,
onChange: ((InventoryGUIClickEvent<T>) -> Unit)?
) : InventoryGUIButton<T>(inventoryGUIElementData, {
) : InventoryGUIButton<T>(icon, {
val currentPage = it.gui.currentPage
val newPage = it.gui.getPage(calculator.calculateNewPage(it.gui.currentPageInt, it.gui.data.pages.keys))

View File

@@ -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<T : ForInventory>(
inventoryGUIElementData: InventoryGUIElementData
) : InventoryGUIElement<T>(inventoryGUIElementData) {
private val icon: ItemStack
) : InventoryGUIElement<T>() {
override fun getItemStack(slot: Int) = icon
override fun onClickElement(clickEvent: InventoryGUIClickEvent<T>) {
clickEvent.bukkitEvent.isCancelled = true

View File

@@ -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<T : ForInventory, E>(
private val compound: InventoryGUISpaceCompound<T, E>
) : InventoryGUIElement<T>() {
override fun getItemStack(slot: Int) = compound.getItemStack(slot)
override fun onClickElement(clickEvent: InventoryGUIClickEvent<T>) {
compound.onClickElement(clickEvent)
}
override fun startUsing(gui: InventoryGUI<*>) = compound.registerGUI(gui)
override fun stopUsing(gui: InventoryGUI<*>) = compound.unregisterGUI(gui)
}
class InventoryGUISpaceCompound<T : ForInventory, E>(
private val invType: InventoryType<T>,
private val iconGenerator: (E) -> ItemStack,
private val onClick: (InventoryGUIClickEvent<T>, E) -> Unit
) {
private val content = ArrayList<E>()
private val realInternalSlots = ArrayList<Int>()
private val currentInternalSlots: List<Int> 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<InventoryGUI<*>>()
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<T>) {
val element = contentAtSlot(clickEvent.bukkitEvent.slot) ?: return
onClick.invoke(clickEvent, element)
}
internal fun addSlots(slots: InventorySlotCompound<T>) {
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 <R : Comparable<R>> 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<E>) {
content += elements
contentSort.invoke()
registeredGUIs.forEach { it.reloadCurrentPage() }
}
}

View File

@@ -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

View File

@@ -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

View File

@@ -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