384 lines
15 KiB
Kotlin
384 lines
15 KiB
Kotlin
@file:Suppress("unused", "MemberVisibilityCanBePrivate")
|
|
|
|
package net.axay.kspigot.gui
|
|
|
|
import net.axay.kspigot.languageextensions.kotlinextensions.MinMaxPair
|
|
|
|
// INVENTORY
|
|
|
|
data class InventoryDimensions(val width: Int, val height: Int) {
|
|
|
|
val slotAmount = width * height
|
|
|
|
val invSlots by lazy {
|
|
ArrayList<InventorySlot>().apply {
|
|
(1..height).forEach { row ->
|
|
(1..width).forEach { slotInRow ->
|
|
this += InventorySlot(row, slotInRow)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
val invSlotsWithRealSlots by lazy {
|
|
HashMap<InventorySlot, Int>().apply {
|
|
invSlots.forEach { curSlot ->
|
|
curSlot.realSlotIn(this@InventoryDimensions)?.let { this[curSlot] = it }
|
|
}
|
|
}
|
|
}
|
|
|
|
val realSlots by lazy { invSlotsWithRealSlots.values }
|
|
|
|
}
|
|
|
|
// SLOTS
|
|
|
|
data class InventorySlot(val row: Int, val slotInRow: Int) : Comparable<InventorySlot> {
|
|
|
|
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.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.height).contains(row)
|
|
|
|
fun add(offsetHorizontally: Int, offsetVertically: Int) = InventorySlot(
|
|
row + offsetVertically,
|
|
slotInRow + offsetHorizontally
|
|
)
|
|
|
|
}
|
|
|
|
interface InventorySlotCompound<out T : ForInventory> {
|
|
|
|
fun withInvType(invType: GUIType<T>): Collection<InventorySlot>
|
|
|
|
fun realSlotsWithInvType(invType: GUIType<T>) =
|
|
withInvType(invType).mapNotNull { it.realSlotIn(invType.dimensions) }
|
|
|
|
}
|
|
|
|
open class SingleInventorySlot<T : ForInventory> internal constructor(
|
|
val inventorySlot: InventorySlot
|
|
) : InventorySlotCompound<T> {
|
|
|
|
constructor(row: Int, slotInRow: Int) : this(InventorySlot(row, slotInRow))
|
|
|
|
private val slotAsList = listOf(inventorySlot)
|
|
|
|
override fun withInvType(invType: GUIType<T>) = slotAsList
|
|
|
|
}
|
|
|
|
internal enum class InventorySlotRangeType {
|
|
LINEAR,
|
|
RECTANGLE,
|
|
}
|
|
|
|
class InventorySlotRange<out T : ForInventory> internal constructor(
|
|
|
|
startSlot: SingleInventorySlot<out T>,
|
|
endSlot: SingleInventorySlot<out T>,
|
|
|
|
private val type: InventorySlotRangeType
|
|
|
|
) : InventorySlotCompound<T>, ClosedRange<InventorySlot> {
|
|
|
|
override val start: InventorySlot
|
|
override val endInclusive: InventorySlot
|
|
|
|
init {
|
|
val minMaxPair = MinMaxPair(startSlot.inventorySlot, endSlot.inventorySlot)
|
|
start = minMaxPair.min
|
|
endInclusive = minMaxPair.max
|
|
}
|
|
|
|
override fun withInvType(invType: GUIType<T>) = LinkedHashSet<InventorySlot>().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)
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* This range contains all slots having an index between
|
|
* the indeces of the two given slots.
|
|
*/
|
|
infix fun <T : ForInventory> SingleInventorySlot<out T>.linTo(slot: SingleInventorySlot<out T>) =
|
|
InventorySlotRange(this, slot, InventorySlotRangeType.LINEAR)
|
|
|
|
/**
|
|
* This range contains all slots inside of a thought rectangle
|
|
* with the two given slots as two opposite corners of the rectangle.
|
|
*/
|
|
infix fun <T : ForInventory> SingleInventorySlot<out T>.rectTo(slot: SingleInventorySlot<out T>) =
|
|
InventorySlotRange(this, slot, InventorySlotRangeType.RECTANGLE)
|
|
|
|
class InventoryRowSlots<T : ForInventory> internal constructor(
|
|
val row: Int
|
|
) : InventorySlotCompound<T> {
|
|
|
|
override fun withInvType(invType: GUIType<T>) = HashSet<InventorySlot>().apply {
|
|
for (slotInRow in 1..invType.dimensions.width)
|
|
this += InventorySlot(row, slotInRow)
|
|
}
|
|
|
|
}
|
|
|
|
class InventoryColumnSlots<T : ForInventory> internal constructor(
|
|
val column: Int
|
|
) : InventorySlotCompound<T> {
|
|
|
|
override fun withInvType(invType: GUIType<T>) = HashSet<InventorySlot>().apply {
|
|
for (row in 1..invType.dimensions.height)
|
|
this += InventorySlot(row, column)
|
|
}
|
|
|
|
}
|
|
|
|
class InventoryBorderSlots<T : ForInventory> internal constructor(
|
|
val padding: Int
|
|
) : InventorySlotCompound<T> {
|
|
|
|
override fun withInvType(invType: GUIType<T>) = HashSet<InventorySlot>().apply {
|
|
|
|
val dimensions = invType.dimensions
|
|
|
|
for (currentPadding in 0 until padding) {
|
|
for (slotInRow in 1 + currentPadding..dimensions.width - currentPadding) {
|
|
this += InventorySlot(1, slotInRow)
|
|
this += InventorySlot(dimensions.height, slotInRow)
|
|
}
|
|
for (row in 2 + currentPadding until dimensions.height - currentPadding) {
|
|
this += InventorySlot(row, 1)
|
|
this += InventorySlot(row, dimensions.width)
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
class InventoryCornerSlots<T : ForInventory> internal constructor(
|
|
val ifBottomLeft: Boolean = false,
|
|
val ifBottomRight: Boolean = false,
|
|
val ifTopLeft: Boolean = false,
|
|
val ifTopRight: Boolean = false
|
|
) : InventorySlotCompound<T> {
|
|
|
|
override fun withInvType(invType: GUIType<T>) = HashSet<InventorySlot>().apply {
|
|
|
|
val dimensions = invType.dimensions
|
|
|
|
if (ifBottomLeft) this += InventorySlot(1, 1)
|
|
if (ifBottomRight) this += InventorySlot(1, dimensions.width)
|
|
if (ifTopLeft) this += InventorySlot(dimensions.height, 1)
|
|
if (ifTopRight) this += InventorySlot(dimensions.height, dimensions.width)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
class InventoryAllSlots<T : ForInventory> : InventorySlotCompound<T> {
|
|
override fun withInvType(invType: GUIType<T>) = invType.dimensions.invSlots
|
|
}
|
|
|
|
// SLOT TYPE SAFETY
|
|
|
|
// COLUMNS
|
|
|
|
interface ForColumnOne : ForInventoryWidthThree, ForInventoryWidthFive, ForInventoryWidthNine
|
|
interface ForColumnTwo : ForInventoryWidthThree, ForInventoryWidthFive, ForInventoryWidthNine
|
|
interface ForColumnThree : ForInventoryWidthThree, ForInventoryWidthFive, ForInventoryWidthNine
|
|
interface ForColumnFour : ForInventoryWidthFive, ForInventoryWidthNine
|
|
interface ForColumnFive : ForInventoryWidthFive, ForInventoryWidthNine
|
|
interface ForColumnSix : ForInventoryWidthNine
|
|
interface ForColumnSeven : ForInventoryWidthNine
|
|
interface ForColumnEight : ForInventoryWidthNine
|
|
interface ForColumnNine : ForInventoryWidthNine
|
|
|
|
// 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
|
|
|
|
// COMPLETE ROWS (including the edge cases)
|
|
interface ForCompleteRowOne : ForRowOne, ForRowOneSlotOneToThree, ForRowOneSlotFourToFive
|
|
interface ForCompleteRowTwo : ForRowTwo, ForRowTwoSlotOneToThree
|
|
interface ForCompleteRowThree : ForRowThree, ForRowThreeSlotOneToThree
|
|
|
|
object Slots {
|
|
|
|
// ROW ONE
|
|
val RowOneSlotOne = SingleInventorySlot<ForRowOneSlotOneToThree>(1, 1)
|
|
val RowOneSlotTwo = SingleInventorySlot<ForRowOneSlotOneToThree>(1, 2)
|
|
val RowOneSlotThree = SingleInventorySlot<ForRowOneSlotOneToThree>(1, 3)
|
|
val RowOneSlotFour = SingleInventorySlot<ForRowOneSlotFourToFive>(1, 4)
|
|
val RowOneSlotFive = SingleInventorySlot<ForRowOneSlotFourToFive>(1, 5)
|
|
val RowOneSlotSix = SingleInventorySlot<ForRowOne>(1, 6)
|
|
val RowOneSlotSeven = SingleInventorySlot<ForRowOne>(1, 7)
|
|
val RowOneSlotEight = SingleInventorySlot<ForRowOne>(1, 8)
|
|
val RowOneSlotNine = SingleInventorySlot<ForRowOne>(1, 9)
|
|
|
|
// ROW TWO
|
|
val RowTwoSlotOne = SingleInventorySlot<ForRowTwoSlotOneToThree>(2, 1)
|
|
val RowTwoSlotTwo = SingleInventorySlot<ForRowTwoSlotOneToThree>(2, 2)
|
|
val RowTwoSlotThree = SingleInventorySlot<ForRowTwoSlotOneToThree>(2, 3)
|
|
val RowTwoSlotFour = SingleInventorySlot<ForRowTwo>(2, 4)
|
|
val RowTwoSlotFive = SingleInventorySlot<ForRowTwo>(2, 5)
|
|
val RowTwoSlotSix = SingleInventorySlot<ForRowTwo>(2, 6)
|
|
val RowTwoSlotSeven = SingleInventorySlot<ForRowTwo>(2, 7)
|
|
val RowTwoSlotEight = SingleInventorySlot<ForRowTwo>(2, 8)
|
|
val RowTwoSlotNine = SingleInventorySlot<ForRowTwo>(2, 9)
|
|
|
|
// ROW THREE
|
|
val RowThreeSlotOne = SingleInventorySlot<ForRowThreeSlotOneToThree>(3, 1)
|
|
val RowThreeSlotTwo = SingleInventorySlot<ForRowThreeSlotOneToThree>(3, 2)
|
|
val RowThreeSlotThree = SingleInventorySlot<ForRowThreeSlotOneToThree>(3, 3)
|
|
val RowThreeSlotFour = SingleInventorySlot<ForRowThree>(3, 4)
|
|
val RowThreeSlotFive = SingleInventorySlot<ForRowThree>(3, 5)
|
|
val RowThreeSlotSix = SingleInventorySlot<ForRowThree>(3, 6)
|
|
val RowThreeSlotSeven = SingleInventorySlot<ForRowThree>(3, 7)
|
|
val RowThreeSlotEight = SingleInventorySlot<ForRowThree>(3, 8)
|
|
val RowThreeSlotNine = SingleInventorySlot<ForRowThree>(3, 9)
|
|
|
|
// ROW FOUR
|
|
val RowFourSlotOne = SingleInventorySlot<ForRowFour>(4, 1)
|
|
val RowFourSlotTwo = SingleInventorySlot<ForRowFour>(4, 2)
|
|
val RowFourSlotThree = SingleInventorySlot<ForRowFour>(4, 3)
|
|
val RowFourSlotFour = SingleInventorySlot<ForRowFour>(4, 4)
|
|
val RowFourSlotFive = SingleInventorySlot<ForRowFour>(4, 5)
|
|
val RowFourSlotSix = SingleInventorySlot<ForRowFour>(4, 6)
|
|
val RowFourSlotSeven = SingleInventorySlot<ForRowFour>(4, 7)
|
|
val RowFourSlotEight = SingleInventorySlot<ForRowFour>(4, 8)
|
|
val RowFourSlotNine = SingleInventorySlot<ForRowFour>(4, 9)
|
|
|
|
// ROW FIVE
|
|
val RowFiveSlotOne = SingleInventorySlot<ForRowFive>(5, 1)
|
|
val RowFiveSlotTwo = SingleInventorySlot<ForRowFive>(5, 2)
|
|
val RowFiveSlotThree = SingleInventorySlot<ForRowFive>(5, 3)
|
|
val RowFiveSlotFour = SingleInventorySlot<ForRowFive>(5, 4)
|
|
val RowFiveSlotFive = SingleInventorySlot<ForRowFive>(5, 5)
|
|
val RowFiveSlotSix = SingleInventorySlot<ForRowFive>(5, 6)
|
|
val RowFiveSlotSeven = SingleInventorySlot<ForRowFive>(5, 7)
|
|
val RowFiveSlotEight = SingleInventorySlot<ForRowFive>(5, 8)
|
|
val RowFiveSlotNine = SingleInventorySlot<ForRowFive>(5, 9)
|
|
|
|
// ROW SIX
|
|
val RowSixSlotOne = SingleInventorySlot<ForRowSix>(6, 1)
|
|
val RowSixSlotTwo = SingleInventorySlot<ForRowSix>(6, 2)
|
|
val RowSixSlotThree = SingleInventorySlot<ForRowSix>(6, 3)
|
|
val RowSixSlotFour = SingleInventorySlot<ForRowSix>(6, 4)
|
|
val RowSixSlotFive = SingleInventorySlot<ForRowSix>(6, 5)
|
|
val RowSixSlotSix = SingleInventorySlot<ForRowSix>(6, 6)
|
|
val RowSixSlotSeven = SingleInventorySlot<ForRowSix>(6, 7)
|
|
val RowSixSlotEight = SingleInventorySlot<ForRowSix>(6, 8)
|
|
val RowSixSlotNine = SingleInventorySlot<ForRowSix>(6, 9)
|
|
|
|
// ROW
|
|
val RowOne = InventoryRowSlots<ForCompleteRowOne>(1)
|
|
val RowTwo = InventoryRowSlots<ForCompleteRowTwo>(2)
|
|
val RowThree = InventoryRowSlots<ForCompleteRowThree>(3)
|
|
val RowFour = InventoryRowSlots<ForRowFour>(4)
|
|
val RowFive = InventoryRowSlots<ForRowFive>(5)
|
|
val RowSix = InventoryRowSlots<ForRowSix>(6)
|
|
|
|
// COLUMN
|
|
val ColumnOne = InventoryColumnSlots<ForColumnOne>(1)
|
|
val ColumnTwo = InventoryColumnSlots<ForColumnTwo>(2)
|
|
val ColumnThree = InventoryColumnSlots<ForColumnThree>(3)
|
|
val ColumnFour = InventoryColumnSlots<ForColumnFour>(4)
|
|
val ColumnFive = InventoryColumnSlots<ForColumnFive>(5)
|
|
val ColumnSix = InventoryColumnSlots<ForColumnSix>(6)
|
|
val ColumnSeven = InventoryColumnSlots<ForColumnSeven>(7)
|
|
val ColumnEight = InventoryColumnSlots<ForColumnEight>(8)
|
|
val ColumnNine = InventoryColumnSlots<ForColumnNine>(9)
|
|
|
|
// BORDER
|
|
val BorderPaddingOne = InventoryBorderSlots<ForEveryInventory>(1)
|
|
val BorderPaddingTwo = InventoryBorderSlots<ForEveryInventory>(2)
|
|
val BorderPaddingThree = InventoryBorderSlots<ForEveryInventory>(3)
|
|
val Border = BorderPaddingOne
|
|
|
|
// CORNER
|
|
val Corners = InventoryCornerSlots<ForEveryInventory>()
|
|
val CornersLeft = InventoryCornerSlots<ForEveryInventory>(ifBottomLeft = true, ifTopLeft = true)
|
|
val CornersRight = InventoryCornerSlots<ForEveryInventory>(ifBottomRight = true, ifTopRight = true)
|
|
val CornersBottom = InventoryCornerSlots<ForEveryInventory>(ifBottomLeft = true, ifBottomRight = true)
|
|
val CornersTop = InventoryCornerSlots<ForEveryInventory>(ifTopLeft = true, ifTopRight = true)
|
|
val CornerBottomLeft = InventoryCornerSlots<ForEveryInventory>(ifBottomLeft = true)
|
|
val CornerBottomRight = InventoryCornerSlots<ForEveryInventory>(ifBottomRight = true)
|
|
val CornerTopLeft = InventoryCornerSlots<ForEveryInventory>(ifTopLeft = true)
|
|
val CornerTopRight = InventoryCornerSlots<ForEveryInventory>(ifTopRight = true)
|
|
|
|
// ALL
|
|
val All = InventoryAllSlots<ForEveryInventory>()
|
|
|
|
} |