diff --git a/interfaces/src/main/kotlin/com/noxcrew/interfaces/InterfacesListeners.kt b/interfaces/src/main/kotlin/com/noxcrew/interfaces/InterfacesListeners.kt index 0f41ad7..21d42fb 100644 --- a/interfaces/src/main/kotlin/com/noxcrew/interfaces/InterfacesListeners.kt +++ b/interfaces/src/main/kotlin/com/noxcrew/interfaces/InterfacesListeners.kt @@ -286,7 +286,7 @@ public class InterfacesListeners private constructor(private val plugin: Plugin) public fun onClick(event: InventoryClickEvent) { val holder = event.inventory.getHolder(false) val view = convertHolderToInterfaceView(holder) ?: return - val clickedPoint = clickedPoint(view, event) ?: return + val clickedPoint = view.backing.mapper.toGridPoint(event.rawSlot) ?: return val isPlayerInventory = (event.clickedInventory ?: event.inventory).getHolder(false) is Player // Run base click handling diff --git a/interfaces/src/main/kotlin/com/noxcrew/interfaces/grid/GridPoint.kt b/interfaces/src/main/kotlin/com/noxcrew/interfaces/grid/GridPoint.kt index 049e00b..24d503b 100644 --- a/interfaces/src/main/kotlin/com/noxcrew/interfaces/grid/GridPoint.kt +++ b/interfaces/src/main/kotlin/com/noxcrew/interfaces/grid/GridPoint.kt @@ -1,7 +1,5 @@ package com.noxcrew.interfaces.grid -import com.noxcrew.interfaces.pane.PlayerPane - /** A 2-dimensional vector storing integer components. */ public data class GridPoint(val x: Int, val y: Int) { @@ -12,11 +10,15 @@ public data class GridPoint(val x: Int, val y: Int) { /** The slot index used to indicate a click was outside the UI. */ public const val OUTSIDE_CHEST_INDEX: Int = -999 + /** Used only on [fromBukkitPlayerSlot], left over from an old system and will be removed when the function is. */ + private val OLD_PANE_MAPPING = listOf(1, 2, 3, 0, 4) + /** Returns the grid point for a [slot] in a player inventory. */ + @Deprecated("Should move everything to use GridMapper instead.") public fun fromBukkitPlayerSlot(slot: Int): GridPoint? { if (slot !in PLAYER_INVENTORY_RANGE) return null val x = slot / 9 - val adjustedX = PlayerPane.PANE_ORDERING.indexOf(x) + val adjustedX = OLD_PANE_MAPPING.indexOf(x) return GridPoint(adjustedX, slot % 9) } diff --git a/interfaces/src/main/kotlin/com/noxcrew/interfaces/grid/mapping/ChestGridMapper.kt b/interfaces/src/main/kotlin/com/noxcrew/interfaces/grid/mapping/ChestGridMapper.kt new file mode 100644 index 0000000..106ae66 --- /dev/null +++ b/interfaces/src/main/kotlin/com/noxcrew/interfaces/grid/mapping/ChestGridMapper.kt @@ -0,0 +1,13 @@ +package com.noxcrew.interfaces.grid.mapping + +import com.noxcrew.interfaces.utilities.gridPointToBukkitIndex + +/** Handles [com.noxcrew.interfaces.grid.GridPoint] mapping for [org.bukkit.event.inventory.InventoryType.CHEST] containers. */ +public open class ChestGridMapper(private val rows: Int) : AbstractGridMapper(), GridMapper.TopInventory { + + override fun toTopInventorySlot(row: Int, column: Int): Int { + return gridPointToBukkitIndex(row, column) + } + + override fun isPlayerInventory(row: Int, column: Int): Boolean = row >= rows +} diff --git a/interfaces/src/main/kotlin/com/noxcrew/interfaces/grid/mapping/CombinedGridMapper.kt b/interfaces/src/main/kotlin/com/noxcrew/interfaces/grid/mapping/CombinedGridMapper.kt new file mode 100644 index 0000000..74d04b3 --- /dev/null +++ b/interfaces/src/main/kotlin/com/noxcrew/interfaces/grid/mapping/CombinedGridMapper.kt @@ -0,0 +1,19 @@ +package com.noxcrew.interfaces.grid.mapping + +import com.noxcrew.interfaces.grid.mapping.GridMapper.PlayerInventory.Companion.PLAYER_INV_ROWS +import com.noxcrew.interfaces.utilities.gridPointToBukkitIndex +import com.noxcrew.interfaces.view.AbstractInterfaceView.Companion.COLUMNS_IN_CHEST + +/** Handles [com.noxcrew.interfaces.grid.GridPoint] mapping for containers combining Chest and Player inventory. */ +public class CombinedGridMapper(private val rows: Int) : ChestGridMapper(rows), GridMapper.PlayerInventory { + + /** Rows of chest times [COLUMNS_IN_CHEST] minus [COLUMNS_IN_CHEST] because 0-8 is in the hot bar. */ + private val chestSize = rows * COLUMNS_IN_CHEST - COLUMNS_IN_CHEST + + override fun toPlayerInventorySlot(row: Int, column: Int): Int { + // If it's not the last row we remove chest size. + if (row < rows + PLAYER_INV_ROWS) return gridPointToBukkitIndex(row, column) - chestSize + // On the last row we use row 0 to map it from 0-8 for the hot bar. + return gridPointToBukkitIndex(0, column) + } +} diff --git a/interfaces/src/main/kotlin/com/noxcrew/interfaces/grid/mapping/GridMapper.kt b/interfaces/src/main/kotlin/com/noxcrew/interfaces/grid/mapping/GridMapper.kt new file mode 100644 index 0000000..f731f6b --- /dev/null +++ b/interfaces/src/main/kotlin/com/noxcrew/interfaces/grid/mapping/GridMapper.kt @@ -0,0 +1,50 @@ +package com.noxcrew.interfaces.grid.mapping + +import com.noxcrew.interfaces.grid.GridPoint +import com.noxcrew.interfaces.grid.GridPoint.Companion.OUTSIDE_CHEST_INDEX + +/** + * Responsible for mapping inventory slots into [GridPoint] and vice versa. + * @see AbstractGridMapper for the default [toGridPoint] implementation. + * @see ChestGridMapper for the [TopInventory] only implementation. + * @see CombinedGridMapper for a combined [TopInventory] and [PlayerInventory] implementation. + * @see PlayerInventoryGridMapper for the [PlayerInventory] only implementation. + */ +public interface GridMapper { + + /** + * This function is called from the listener where the [slot] is the `rawSlot` representation. + * This means that slots will go from 0 to x as opposed to normal slots which are based on the inventory they are in. + */ + public fun toGridPoint(slot: Int): GridPoint? + + /** Whether the [GridPoint] is in the player's inventory. */ + public fun isPlayerInventory(row: Int, column: Int): Boolean + + /** Responsible for mapping [GridPoint] into top inventory slots. */ + public interface TopInventory : GridMapper { + /** The slot returned should be relative to the inventory it is in. */ + public fun toTopInventorySlot(row: Int, column: Int): Int + } + + /** + * Responsible for mapping [GridPoint] into player inventory slots. + * Which cane be completely different based on the type of the [TopInventory]. + */ + public interface PlayerInventory : GridMapper { + public companion object { + public const val PLAYER_INV_ROWS: Int = 3 + } + + /** The slot returned is relevant to the PlayerInventory mapping, normally 0-8 is the hot bar. */ + public fun toPlayerInventorySlot(row: Int, column: Int): Int + } +} + +/** Simple implementation for [toGridPoint] that can be shared by multiple [GridMapper] (assumes chest-based containers). */ +public abstract class AbstractGridMapper : GridMapper { + override fun toGridPoint(slot: Int): GridPoint? { + if (slot == OUTSIDE_CHEST_INDEX) return null + return GridPoint(slot / 9, slot % 9) + } +} diff --git a/interfaces/src/main/kotlin/com/noxcrew/interfaces/grid/mapping/PlayerInventoryGridMapper.kt b/interfaces/src/main/kotlin/com/noxcrew/interfaces/grid/mapping/PlayerInventoryGridMapper.kt new file mode 100644 index 0000000..7d79090 --- /dev/null +++ b/interfaces/src/main/kotlin/com/noxcrew/interfaces/grid/mapping/PlayerInventoryGridMapper.kt @@ -0,0 +1,40 @@ +package com.noxcrew.interfaces.grid.mapping + +import com.noxcrew.interfaces.grid.GridPoint +import com.noxcrew.interfaces.grid.mapping.GridMapper.PlayerInventory.Companion.PLAYER_INV_ROWS +import com.noxcrew.interfaces.utilities.gridPointToBukkitIndex +import com.noxcrew.interfaces.view.AbstractInterfaceView.Companion.COLUMNS_IN_CHEST + +/** + * Handles [GridPoint] mapping for the player's own inventory. + * Including armor slots and offhand. + */ +public object PlayerInventoryGridMapper : AbstractGridMapper(), GridMapper.PlayerInventory { + + private const val PLAYER_INV_SIZE = PLAYER_INV_ROWS * COLUMNS_IN_CHEST + private const val PLAYER_INV_HOT_BAR_SIZE = PLAYER_INV_SIZE + COLUMNS_IN_CHEST + + override fun toGridPoint(slot: Int): GridPoint? { + // Hot bar slot. + if (slot >= PLAYER_INV_HOT_BAR_SIZE + COLUMNS_IN_CHEST) { + return super.toGridPoint(slot) + } + + // "Extra" slots, armor, offhand, crafting grid. + if (slot < COLUMNS_IN_CHEST) { + return super.toGridPoint(slot + PLAYER_INV_HOT_BAR_SIZE) + } + + // Everything else we just shift it up by 9 slots. + return super.toGridPoint(slot - COLUMNS_IN_CHEST) + } + + override fun toPlayerInventorySlot(row: Int, column: Int): Int { + // If it's not the last row we remove chest size. + if (row < PLAYER_INV_ROWS) return gridPointToBukkitIndex(row, column) - COLUMNS_IN_CHEST + // On the last row we use row 0 to map it from 0-8 for the hot bar. + return gridPointToBukkitIndex(0, column) + } + + override fun isPlayerInventory(row: Int, column: Int): Boolean = true +} diff --git a/interfaces/src/main/kotlin/com/noxcrew/interfaces/interfaces/ChestInterface.kt b/interfaces/src/main/kotlin/com/noxcrew/interfaces/interfaces/ChestInterface.kt index 7a7018e..ee5e215 100644 --- a/interfaces/src/main/kotlin/com/noxcrew/interfaces/interfaces/ChestInterface.kt +++ b/interfaces/src/main/kotlin/com/noxcrew/interfaces/interfaces/ChestInterface.kt @@ -1,5 +1,6 @@ package com.noxcrew.interfaces.interfaces +import com.noxcrew.interfaces.grid.mapping.ChestGridMapper import com.noxcrew.interfaces.pane.Pane import com.noxcrew.interfaces.view.ChestInterfaceView import com.noxcrew.interfaces.view.InterfaceView @@ -19,6 +20,7 @@ public class ChestInterface internal constructor( } override val includesPlayerInventory: Boolean = false + override val mapper: ChestGridMapper = ChestGridMapper(rows) override fun createPane(): Pane = Pane() diff --git a/interfaces/src/main/kotlin/com/noxcrew/interfaces/interfaces/CombinedInterface.kt b/interfaces/src/main/kotlin/com/noxcrew/interfaces/interfaces/CombinedInterface.kt index f1cfc11..5921924 100644 --- a/interfaces/src/main/kotlin/com/noxcrew/interfaces/interfaces/CombinedInterface.kt +++ b/interfaces/src/main/kotlin/com/noxcrew/interfaces/interfaces/CombinedInterface.kt @@ -1,5 +1,6 @@ package com.noxcrew.interfaces.interfaces +import com.noxcrew.interfaces.grid.mapping.CombinedGridMapper import com.noxcrew.interfaces.pane.CombinedPane import com.noxcrew.interfaces.view.CombinedInterfaceView import com.noxcrew.interfaces.view.InterfaceView @@ -10,7 +11,7 @@ import org.bukkit.entity.Player public class CombinedInterface internal constructor( override val rows: Int, override val initialTitle: Component?, - override val builder: CombinedInterfaceBuilder + override val builder: CombinedInterfaceBuilder, ) : Interface, TitledInterface { public companion object { @@ -19,6 +20,7 @@ public class CombinedInterface internal constructor( } override val includesPlayerInventory: Boolean = true + override val mapper: CombinedGridMapper = CombinedGridMapper(rows) override fun totalRows(): Int = rows + 4 diff --git a/interfaces/src/main/kotlin/com/noxcrew/interfaces/interfaces/Interface.kt b/interfaces/src/main/kotlin/com/noxcrew/interfaces/interfaces/Interface.kt index fbdbf44..b04d52b 100644 --- a/interfaces/src/main/kotlin/com/noxcrew/interfaces/interfaces/Interface.kt +++ b/interfaces/src/main/kotlin/com/noxcrew/interfaces/interfaces/Interface.kt @@ -2,6 +2,7 @@ package com.noxcrew.interfaces.interfaces import com.noxcrew.interfaces.InterfacesListeners import com.noxcrew.interfaces.grid.GridPoint +import com.noxcrew.interfaces.grid.mapping.GridMapper import com.noxcrew.interfaces.pane.CombinedPane import com.noxcrew.interfaces.pane.Pane import com.noxcrew.interfaces.view.InterfaceView @@ -16,6 +17,9 @@ public interface Interface, P : Pane> { /** The builder that creates this interface. */ public val builder: InterfaceBuilder + /** The [GridMapper] to convert from and to [GridPoint]. */ + public val mapper: GridMapper + /** Whether this view includes the player inventory. */ public val includesPlayerInventory: Boolean diff --git a/interfaces/src/main/kotlin/com/noxcrew/interfaces/interfaces/PlayerInterface.kt b/interfaces/src/main/kotlin/com/noxcrew/interfaces/interfaces/PlayerInterface.kt index f4b1bd4..f7c0324 100644 --- a/interfaces/src/main/kotlin/com/noxcrew/interfaces/interfaces/PlayerInterface.kt +++ b/interfaces/src/main/kotlin/com/noxcrew/interfaces/interfaces/PlayerInterface.kt @@ -1,5 +1,6 @@ package com.noxcrew.interfaces.interfaces +import com.noxcrew.interfaces.grid.mapping.PlayerInventoryGridMapper import com.noxcrew.interfaces.pane.PlayerPane import com.noxcrew.interfaces.view.InterfaceView import com.noxcrew.interfaces.view.PlayerInterfaceView @@ -16,6 +17,7 @@ public class PlayerInterface internal constructor( } override val includesPlayerInventory: Boolean = true + override val mapper: PlayerInventoryGridMapper = PlayerInventoryGridMapper override val rows: Int = 4 diff --git a/interfaces/src/main/kotlin/com/noxcrew/interfaces/inventory/ChestInterfacesInventory.kt b/interfaces/src/main/kotlin/com/noxcrew/interfaces/inventory/ChestInterfacesInventory.kt index 02b4455..4758a94 100644 --- a/interfaces/src/main/kotlin/com/noxcrew/interfaces/inventory/ChestInterfacesInventory.kt +++ b/interfaces/src/main/kotlin/com/noxcrew/interfaces/inventory/ChestInterfacesInventory.kt @@ -1,7 +1,7 @@ package com.noxcrew.interfaces.inventory +import com.noxcrew.interfaces.grid.mapping.ChestGridMapper import com.noxcrew.interfaces.utilities.createBukkitInventory -import com.noxcrew.interfaces.utilities.gridPointToBukkitIndex import net.kyori.adventure.text.Component import org.bukkit.inventory.Inventory import org.bukkit.inventory.InventoryHolder @@ -11,21 +11,18 @@ import org.bukkit.inventory.ItemStack public class ChestInterfacesInventory( holder: InventoryHolder, title: Component?, - rows: Int + rows: Int, + private val mapper: ChestGridMapper, ) : CachedInterfacesInventory() { /** The [chestInventory] being used to place items in. */ public val chestInventory: Inventory = createBukkitInventory(holder, rows, title) override fun get(row: Int, column: Int): ItemStack? { - val index = gridPointToBukkitIndex(row, column) - return chestInventory.getItem(index) + return chestInventory.getItem(mapper.toTopInventorySlot(row, column)) } override fun setInternal(row: Int, column: Int, item: ItemStack?) { - val index = gridPointToBukkitIndex(row, column) - chestInventory.setItem(index, item) + chestInventory.setItem(mapper.toTopInventorySlot(row, column), item) } - - override fun isPlayerInventory(row: Int, column: Int): Boolean = false } diff --git a/interfaces/src/main/kotlin/com/noxcrew/interfaces/inventory/CombinedInterfacesInventory.kt b/interfaces/src/main/kotlin/com/noxcrew/interfaces/inventory/CombinedInterfacesInventory.kt index d002d55..b1f4e44 100644 --- a/interfaces/src/main/kotlin/com/noxcrew/interfaces/inventory/CombinedInterfacesInventory.kt +++ b/interfaces/src/main/kotlin/com/noxcrew/interfaces/inventory/CombinedInterfacesInventory.kt @@ -1,8 +1,7 @@ package com.noxcrew.interfaces.inventory +import com.noxcrew.interfaces.grid.mapping.CombinedGridMapper import com.noxcrew.interfaces.utilities.createBukkitInventory -import com.noxcrew.interfaces.utilities.gridPointToBukkitIndex -import com.noxcrew.interfaces.view.AbstractInterfaceView.Companion.COLUMNS_IN_CHEST import net.kyori.adventure.text.Component import org.bukkit.entity.Player import org.bukkit.inventory.Inventory @@ -15,37 +14,29 @@ public class CombinedInterfacesInventory( holder: InventoryHolder, player: Player, title: Component?, - private val rows: Int + private val rows: Int, + private val mapper: CombinedGridMapper, ) : CachedInterfacesInventory() { - private val chestSlots = rows * COLUMNS_IN_CHEST private val playerInventory = player.inventory /** The [chestInventory] being used to place items in. */ public val chestInventory: Inventory = createBukkitInventory(holder, rows, title) override fun get(row: Int, column: Int): ItemStack? { - val bukkitIndex = gridPointToBukkitIndex(row, column) - - if (row >= rows) { - val adjustedIndex = bukkitIndex - chestSlots - return playerInventory.getItem(adjustedIndex) + if (mapper.isPlayerInventory(row, column)) { + return playerInventory.getItem(mapper.toPlayerInventorySlot(row, column)) } - return chestInventory.getItem(bukkitIndex) + return chestInventory.getItem(mapper.toTopInventorySlot(row, column)) } override fun setInternal(row: Int, column: Int, item: ItemStack?) { - val bukkitIndex = gridPointToBukkitIndex(row, column) - - if (row >= rows) { - val adjustedIndex = bukkitIndex - chestSlots - playerInventory.setItem(adjustedIndex, item) + if (mapper.isPlayerInventory(row, column)) { + playerInventory.setItem(mapper.toPlayerInventorySlot(row, column), item) return } - chestInventory.setItem(bukkitIndex, item) + chestInventory.setItem(mapper.toTopInventorySlot(row, column), item) } - - override fun isPlayerInventory(row: Int, column: Int): Boolean = row >= rows } diff --git a/interfaces/src/main/kotlin/com/noxcrew/interfaces/inventory/InterfacesInventory.kt b/interfaces/src/main/kotlin/com/noxcrew/interfaces/inventory/InterfacesInventory.kt index d0116a4..cf834d5 100644 --- a/interfaces/src/main/kotlin/com/noxcrew/interfaces/inventory/InterfacesInventory.kt +++ b/interfaces/src/main/kotlin/com/noxcrew/interfaces/inventory/InterfacesInventory.kt @@ -5,9 +5,6 @@ import org.bukkit.inventory.ItemStack /** Represents some inventory that item stacks can be placed into. */ public interface InterfacesInventory { - /** Returns whether ([row], [column]) falls within a player's inventory. */ - public fun isPlayerInventory(row: Int, column: Int): Boolean - /** Sets the item at ([row], [column]) to [item]. */ public fun set(row: Int, column: Int, item: ItemStack?): Boolean diff --git a/interfaces/src/main/kotlin/com/noxcrew/interfaces/inventory/PlayerInterfacesInventory.kt b/interfaces/src/main/kotlin/com/noxcrew/interfaces/inventory/PlayerInterfacesInventory.kt index 9eb119f..7e34258 100644 --- a/interfaces/src/main/kotlin/com/noxcrew/interfaces/inventory/PlayerInterfacesInventory.kt +++ b/interfaces/src/main/kotlin/com/noxcrew/interfaces/inventory/PlayerInterfacesInventory.kt @@ -1,26 +1,68 @@ package com.noxcrew.interfaces.inventory -import com.noxcrew.interfaces.utilities.gridPointToBukkitIndex +import com.noxcrew.interfaces.grid.mapping.PlayerInventoryGridMapper +import com.noxcrew.interfaces.pane.PlayerPane.Companion.BOOTS_SLOT +import com.noxcrew.interfaces.pane.PlayerPane.Companion.CHEST_SLOT +import com.noxcrew.interfaces.pane.PlayerPane.Companion.EXTRA_ROW +import com.noxcrew.interfaces.pane.PlayerPane.Companion.HELMET_SLOT +import com.noxcrew.interfaces.pane.PlayerPane.Companion.LEGGING_SLOT +import com.noxcrew.interfaces.pane.PlayerPane.Companion.OFFHAND_ROW import org.bukkit.entity.Player import org.bukkit.inventory.ItemStack import org.bukkit.inventory.PlayerInventory /** A wrapper around a [PlayerInventory]. */ public class PlayerInterfacesInventory( - player: Player + player: Player, + private val mapper: PlayerInventoryGridMapper, ) : CachedInterfacesInventory() { private val playerInventory = player.inventory override fun get(row: Int, column: Int): ItemStack? { - val index = gridPointToBukkitIndex(row, column) - return playerInventory.getItem(index) + // First handle the offhand slot. + if (row == OFFHAND_ROW) { + return playerInventory.itemInOffHand + } + + // Handle crafting and armor. + if (row == EXTRA_ROW) { + return when (column) { + // Armor slots. + HELMET_SLOT.y -> playerInventory.helmet + CHEST_SLOT.y -> playerInventory.chestplate + LEGGING_SLOT.y -> playerInventory.leggings + BOOTS_SLOT.y -> playerInventory.boots + + // In the future could add support for crafting grid slots. + else -> null + } + } + + // Lastly, all normal items. + return playerInventory.getItem(mapper.toPlayerInventorySlot(row, column)) } override fun setInternal(row: Int, column: Int, item: ItemStack?) { - val index = gridPointToBukkitIndex(row, column) - return playerInventory.setItem(index, item) - } + // First handle the offhand slot. + if (row == OFFHAND_ROW) { + playerInventory.setItemInOffHand(item) + return + } + + // Handle crafting and armor. + if (row == EXTRA_ROW) { + when (column) { + // Armor slots. + HELMET_SLOT.y -> playerInventory.helmet = item + CHEST_SLOT.y -> playerInventory.chestplate = item + LEGGING_SLOT.y -> playerInventory.leggings = item + BOOTS_SLOT.y -> playerInventory.boots = item + } + return + } - override fun isPlayerInventory(row: Int, column: Int): Boolean = true + // Lastly, all normal items. + playerInventory.setItem(mapper.toPlayerInventorySlot(row, column), item) + } } diff --git a/interfaces/src/main/kotlin/com/noxcrew/interfaces/pane/CombinedPane.kt b/interfaces/src/main/kotlin/com/noxcrew/interfaces/pane/CombinedPane.kt index b2ffaad..e6cdd2f 100644 --- a/interfaces/src/main/kotlin/com/noxcrew/interfaces/pane/CombinedPane.kt +++ b/interfaces/src/main/kotlin/com/noxcrew/interfaces/pane/CombinedPane.kt @@ -1,22 +1,4 @@ package com.noxcrew.interfaces.pane /** A combined pane where a given amount of chest rows are followed by the 4 player inventory rows. */ -public class CombinedPane( - public val chestRows: Int -) : OrderedPane(createMappings(chestRows)) { - - public companion object { - /** Creates mappings for a combined view with [rows] rows. */ - public fun createMappings(rows: Int): List = buildList { - IntRange(0, rows - 1).forEach(::add) - - // the players hotbar is row 0 in the players inventory, - // for combined interfaces it makes more sense for hotbar - // to be the last row, so reshuffle here. - add(rows + 1) - add(rows + 2) - add(rows + 3) - add(rows) - } - } -} +public class CombinedPane(public val chestRows: Int) : Pane() diff --git a/interfaces/src/main/kotlin/com/noxcrew/interfaces/pane/CompletedPane.kt b/interfaces/src/main/kotlin/com/noxcrew/interfaces/pane/CompletedPane.kt index d8a9d94..a010a4c 100644 --- a/interfaces/src/main/kotlin/com/noxcrew/interfaces/pane/CompletedPane.kt +++ b/interfaces/src/main/kotlin/com/noxcrew/interfaces/pane/CompletedPane.kt @@ -13,21 +13,11 @@ import org.bukkit.entity.Player /** A grid map of completed elements. */ public open class CompletedPane : GridMap by HashGridMap() { public open fun getRaw(vector: GridPoint): CompletedElement? = get(vector) - - public open fun getRawUnordered(vector: GridPoint): CompletedElement? = get(vector) -} - -/** A completed pane with an ordering. */ -internal class CompletedOrderedPane( - private val ordering: List -) : CompletedPane() { - - override fun getRaw(vector: GridPoint): CompletedElement? = ordering.getOrNull(vector.x)?.let { get(it, vector.y) } } /** Completes a pane for [player] by drawing each element while suspending. */ internal suspend fun Pane.complete(player: Player): CompletedPane { - val pane = convertToEmptyCompletedPane() + val pane = CompletedPane() forEachSuspending { row, column, element -> pane[row, column] = element.complete(player) @@ -38,7 +28,7 @@ internal suspend fun Pane.complete(player: Player): CompletedPane { /** Fills up a completed pane with empty elements. */ internal fun Pane.convertToEmptyCompletedPaneAndFill(rows: Int): CompletedPane { - val pane = convertToEmptyCompletedPane() + val pane = CompletedPane() val airElement = CompletedElement(null, ClickHandler.EMPTY) forEachInGrid(rows, COLUMNS_IN_CHEST) { row, column -> @@ -47,11 +37,3 @@ internal fun Pane.convertToEmptyCompletedPaneAndFill(rows: Int): CompletedPane { return pane } - -/** Converts this pane to either a [CompletedPane] or [CompletedOrderedPane] based on its type. */ -internal fun Pane.convertToEmptyCompletedPane(): CompletedPane { - if (this is OrderedPane) { - return CompletedOrderedPane(ordering) - } - return CompletedPane() -} diff --git a/interfaces/src/main/kotlin/com/noxcrew/interfaces/pane/OrderedPane.kt b/interfaces/src/main/kotlin/com/noxcrew/interfaces/pane/OrderedPane.kt deleted file mode 100644 index 94db718..0000000 --- a/interfaces/src/main/kotlin/com/noxcrew/interfaces/pane/OrderedPane.kt +++ /dev/null @@ -1,23 +0,0 @@ -package com.noxcrew.interfaces.pane - -import com.noxcrew.interfaces.element.Element - -/** A pane where row indices are re-ordered using [ordering]. */ -public abstract class OrderedPane( - internal val ordering: List -) : Pane() { - - override fun get(row: Int, column: Int): Element? { - return super.get(orderedRow(row), column) - } - - override fun set(row: Int, column: Int, value: Element) { - return super.set(orderedRow(row), column, value) - } - - override fun has(row: Int, column: Int): Boolean { - return super.has(orderedRow(row), column) - } - - private fun orderedRow(row: Int) = ordering[row] -} diff --git a/interfaces/src/main/kotlin/com/noxcrew/interfaces/pane/PlayerPane.kt b/interfaces/src/main/kotlin/com/noxcrew/interfaces/pane/PlayerPane.kt index 46df849..dff96e2 100644 --- a/interfaces/src/main/kotlin/com/noxcrew/interfaces/pane/PlayerPane.kt +++ b/interfaces/src/main/kotlin/com/noxcrew/interfaces/pane/PlayerPane.kt @@ -4,14 +4,25 @@ import com.noxcrew.interfaces.element.Element import com.noxcrew.interfaces.grid.GridPoint /** An ordered pane that wraps the player inventory. */ -public class PlayerPane : OrderedPane(PANE_ORDERING) { +public class PlayerPane : Pane() { internal companion object { - /** The base ordering of the player inventory to go from logical rows to Bukkit rows. */ - internal val PANE_ORDERING = listOf(1, 2, 3, 0, 4) + /** The row used for the hot bar slots. */ + internal const val HOT_BAR_ROW = 3 + + /** The row used for armor and crafting slots. */ + internal const val EXTRA_ROW = 4 + + /** The row used for the offhand slot. */ + internal const val OFFHAND_ROW = 5 /** The location of the off-hand slot. */ - internal val OFF_HAND_SLOT = GridPoint.at(4, 4) + internal val OFF_HAND_SLOT = GridPoint.at(OFFHAND_ROW, 0) + + internal val HELMET_SLOT = GridPoint.at(EXTRA_ROW, 5) + internal val CHEST_SLOT = GridPoint.at(EXTRA_ROW, 6) + internal val LEGGING_SLOT = GridPoint.at(EXTRA_ROW, 7) + internal val BOOTS_SLOT = GridPoint.at(EXTRA_ROW, 8) } /** The hotbar of the player inventory. */ @@ -27,31 +38,31 @@ public class PlayerPane : OrderedPane(PANE_ORDERING) { public inner class Hotbar { /** Returns the item in the hotbar at the [slot]-th slot. */ - public operator fun get(slot: Int): Element? = get(3, slot) + public operator fun get(slot: Int): Element? = get(HOT_BAR_ROW, slot) /** Sets the item in the hotbar at the [slot]-th slot to [value]. */ - public operator fun set(slot: Int, value: Element): Unit = set(3, slot, value) + public operator fun set(slot: Int, value: Element): Unit = set(HOT_BAR_ROW, slot, value) } public inner class Armor { /** The helmet slot of the player's armor items. */ public var helmet: Element - get() = get(4, 3) ?: Element.EMPTY - set(value) = set(4, 3, value) + get() = get(HELMET_SLOT) ?: Element.EMPTY + set(value) = set(HELMET_SLOT, value) /** The chest slot of the player's armor items. */ public var chest: Element - get() = get(4, 2) ?: Element.EMPTY - set(value) = set(4, 2, value) + get() = get(CHEST_SLOT) ?: Element.EMPTY + set(value) = set(CHEST_SLOT, value) - /** The leggings slot of the player's armor items. */ + /** The legging slot of the player's armor items. */ public var leggings: Element - get() = get(4, 1) ?: Element.EMPTY - set(value) = set(4, 1, value) + get() = get(LEGGING_SLOT) ?: Element.EMPTY + set(value) = set(LEGGING_SLOT, value) /** The boots slot of the player's armor items. */ public var boots: Element - get() = get(4, 0) ?: Element.EMPTY - set(value) = set(4, 0, value) + get() = get(BOOTS_SLOT) ?: Element.EMPTY + set(value) = set(BOOTS_SLOT, value) } } diff --git a/interfaces/src/main/kotlin/com/noxcrew/interfaces/utilities/CollapsablePaneMap.kt b/interfaces/src/main/kotlin/com/noxcrew/interfaces/utilities/CollapsablePaneMap.kt index 7f83e52..4b2e780 100644 --- a/interfaces/src/main/kotlin/com/noxcrew/interfaces/utilities/CollapsablePaneMap.kt +++ b/interfaces/src/main/kotlin/com/noxcrew/interfaces/utilities/CollapsablePaneMap.kt @@ -2,7 +2,6 @@ package com.noxcrew.interfaces.utilities import com.noxcrew.interfaces.pane.CompletedPane import com.noxcrew.interfaces.pane.Pane -import com.noxcrew.interfaces.pane.convertToEmptyCompletedPane import com.noxcrew.interfaces.pane.convertToEmptyCompletedPaneAndFill /** A collection of completed panes that can be collapsed to create a new merged [CompletedPane]. */ @@ -35,7 +34,7 @@ internal class CollapsablePaneMap private constructor( return pane } - val pane = if (fill) basePane.convertToEmptyCompletedPaneAndFill(rows) else basePane.convertToEmptyCompletedPane() + val pane = if (fill) basePane.convertToEmptyCompletedPaneAndFill(rows) else CompletedPane() val current = internal.toMap().values current.forEach { layer -> diff --git a/interfaces/src/main/kotlin/com/noxcrew/interfaces/view/AbstractInterfaceView.kt b/interfaces/src/main/kotlin/com/noxcrew/interfaces/view/AbstractInterfaceView.kt index 6163fbb..e1b52c8 100644 --- a/interfaces/src/main/kotlin/com/noxcrew/interfaces/view/AbstractInterfaceView.kt +++ b/interfaces/src/main/kotlin/com/noxcrew/interfaces/view/AbstractInterfaceView.kt @@ -54,6 +54,8 @@ public abstract class AbstractInterfaceView, Unit>() /** The builder used by this interface. */ @@ -341,7 +343,7 @@ public abstract class AbstractInterfaceView // We defer drawing of any elements in the player inventory itself // for later unless the inventory is already open. - val isPlayerInventory = currentInventory.isPlayerInventory(row, column) + val isPlayerInventory = mapper.isPlayerInventory(row, column) if ((!drawNormalInventory && !isPlayerInventory) || (!drawPlayerInventory && isPlayerInventory)) return@forEach currentInventory.set( @@ -358,7 +360,7 @@ public abstract class AbstractInterfaceView( player, backing, - parent + parent, ), InventoryHolder { @@ -28,9 +28,10 @@ public class ChestInterfaceView internal constructor( } override fun createInventory(): ChestInterfacesInventory = ChestInterfacesInventory( - this, - titleState.current, - backing.rows + holder = this, + title = titleState.current, + rows = backing.rows, + mapper = backing.mapper, ) override fun openInventory() { diff --git a/interfaces/src/main/kotlin/com/noxcrew/interfaces/view/CombinedInterfaceView.kt b/interfaces/src/main/kotlin/com/noxcrew/interfaces/view/CombinedInterfaceView.kt index 57c8d86..5af2a9c 100644 --- a/interfaces/src/main/kotlin/com/noxcrew/interfaces/view/CombinedInterfaceView.kt +++ b/interfaces/src/main/kotlin/com/noxcrew/interfaces/view/CombinedInterfaceView.kt @@ -13,11 +13,11 @@ import org.bukkit.inventory.InventoryHolder public class CombinedInterfaceView internal constructor( player: Player, backing: CombinedInterface, - parent: InterfaceView? + parent: InterfaceView?, ) : AbstractInterfaceView( player, backing, - parent + parent, ), InventoryHolder { @@ -28,10 +28,11 @@ public class CombinedInterfaceView internal constructor( } override fun createInventory(): CombinedInterfacesInventory = CombinedInterfacesInventory( - this, - player, - titleState.current, - backing.rows + holder = this, + player = player, + title = titleState.current, + rows = backing.rows, + mapper = backing.mapper, ) override fun openInventory() { diff --git a/interfaces/src/main/kotlin/com/noxcrew/interfaces/view/PlayerInterfaceView.kt b/interfaces/src/main/kotlin/com/noxcrew/interfaces/view/PlayerInterfaceView.kt index ef69b95..ae73dba 100644 --- a/interfaces/src/main/kotlin/com/noxcrew/interfaces/view/PlayerInterfaceView.kt +++ b/interfaces/src/main/kotlin/com/noxcrew/interfaces/view/PlayerInterfaceView.kt @@ -29,7 +29,7 @@ public class PlayerInterfaceView internal constructor( error("PlayerInventoryView does not support chat queries") } - override fun createInventory(): PlayerInterfacesInventory = PlayerInterfacesInventory(player) + override fun createInventory(): PlayerInterfacesInventory = PlayerInterfacesInventory(player, backing.mapper) override fun openInventory() { // Close whatever inventory the player has open so they can look at their normal inventory!