Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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) {

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

Expand Down
Original file line number Diff line number Diff line change
@@ -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
}
Original file line number Diff line number Diff line change
@@ -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)
}
}
Original file line number Diff line number Diff line change
@@ -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)
}
}
Original file line number Diff line number Diff line change
@@ -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
}
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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()

Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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<CombinedInterface, CombinedPane>, TitledInterface {

public companion object {
Expand All @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -16,6 +17,9 @@ public interface Interface<I : Interface<I, P>, P : Pane> {
/** The builder that creates this interface. */
public val builder: InterfaceBuilder<P, I>

/** The [GridMapper] to convert from and to [GridPoint]. */
public val mapper: GridMapper

/** Whether this view includes the player inventory. */
public val includesPlayerInventory: Boolean

Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -16,6 +17,7 @@ public class PlayerInterface internal constructor(
}

override val includesPlayerInventory: Boolean = true
override val mapper: PlayerInventoryGridMapper = PlayerInventoryGridMapper

override val rows: Int = 4

Expand Down
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
}
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
}
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Loading