Major improvements to menus
This commit is contained in:
@@ -4,8 +4,8 @@ import com.willfp.eco.core.gui.component.GUIComponent
|
||||
import com.willfp.eco.core.gui.menu.CloseHandler
|
||||
import com.willfp.eco.core.gui.menu.Menu
|
||||
import com.willfp.eco.core.gui.menu.OpenHandler
|
||||
import com.willfp.eco.core.gui.slot.FillerSlot
|
||||
import com.willfp.eco.core.gui.slot.Slot
|
||||
import com.willfp.eco.internal.gui.slot.EcoFillerSlot
|
||||
import com.willfp.eco.util.NamespacedKeyUtils
|
||||
import org.bukkit.Bukkit
|
||||
import org.bukkit.Material
|
||||
@@ -19,39 +19,44 @@ import org.bukkit.persistence.PersistentDataType
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
class EcoMenu(
|
||||
private val rows: Int,
|
||||
private val componentsAtPoints: Map<Anchor, OffsetComponent>,
|
||||
private val componentsAtPoints: Map<Anchor, List<OffsetComponent>>,
|
||||
private val title: String,
|
||||
private val onClose: CloseHandler,
|
||||
private val onRender: (Player, Menu) -> Unit,
|
||||
private val onOpen: OpenHandler
|
||||
) : Menu {
|
||||
private fun getComponent(row: Int, column: Int): OffsetComponent? {
|
||||
private fun getPossiblyReactiveSlot(row: Int, column: Int, player: Player?, menu: Menu?): Slot {
|
||||
if (row < 1 || row > this.rows || column < 1 || column > 9) {
|
||||
return emptyOffsetComponent
|
||||
return emptyFillerSlot
|
||||
}
|
||||
|
||||
return componentsAtPoints[Anchor(row, column)]
|
||||
val anchor = Anchor(row, column)
|
||||
val components = componentsAtPoints[anchor] ?: return emptyFillerSlot
|
||||
|
||||
for (component in components) {
|
||||
val found = if (player != null && menu != null) component.component.getSlotAt(
|
||||
component.rowOffset,
|
||||
component.columnOffset,
|
||||
player,
|
||||
menu
|
||||
) else component.component.getSlotAt(
|
||||
component.rowOffset,
|
||||
component.columnOffset
|
||||
)
|
||||
|
||||
if (found != null) {
|
||||
return found
|
||||
}
|
||||
}
|
||||
|
||||
return emptyFillerSlot
|
||||
}
|
||||
|
||||
override fun getSlot(row: Int, column: Int): Slot {
|
||||
val found = getComponent(row, column) ?: return emptyFillerSlot
|
||||
override fun getSlot(row: Int, column: Int): Slot =
|
||||
getPossiblyReactiveSlot(row, column, null, null)
|
||||
|
||||
return found.component.getSlotAt(
|
||||
found.rowOffset,
|
||||
found.columnOffset
|
||||
) ?: emptyFillerSlot
|
||||
}
|
||||
|
||||
override fun getSlot(row: Int, column: Int, player: Player, menu: Menu): Slot {
|
||||
val found = getComponent(row, column) ?: return emptyFillerSlot
|
||||
|
||||
return found.component.getSlotAt(
|
||||
found.rowOffset,
|
||||
found.columnOffset,
|
||||
player,
|
||||
menu
|
||||
) ?: emptyFillerSlot
|
||||
}
|
||||
override fun getSlot(row: Int, column: Int, player: Player, menu: Menu): Slot =
|
||||
getPossiblyReactiveSlot(row, column, player, menu)
|
||||
|
||||
override fun open(player: Player): Inventory {
|
||||
val inventory = Bukkit.createInventory(null, rows * 9, title)
|
||||
@@ -146,5 +151,5 @@ data class Anchor(
|
||||
val column: Int
|
||||
)
|
||||
|
||||
val emptyFillerSlot = EcoFillerSlot(ItemStack(Material.AIR))
|
||||
val emptyFillerSlot = FillerSlot(ItemStack(Material.AIR))
|
||||
val emptyOffsetComponent = OffsetComponent(emptyFillerSlot, 0, 0)
|
||||
|
||||
@@ -5,9 +5,6 @@ import com.willfp.eco.core.gui.menu.CloseHandler
|
||||
import com.willfp.eco.core.gui.menu.Menu
|
||||
import com.willfp.eco.core.gui.menu.MenuBuilder
|
||||
import com.willfp.eco.core.gui.menu.OpenHandler
|
||||
import com.willfp.eco.core.gui.slot.FillerMask
|
||||
import com.willfp.eco.core.gui.slot.Slot
|
||||
import com.willfp.eco.util.ListUtils
|
||||
import com.willfp.eco.util.StringUtils
|
||||
import org.bukkit.entity.Player
|
||||
import java.util.function.BiConsumer
|
||||
@@ -15,8 +12,7 @@ import java.util.function.Consumer
|
||||
|
||||
class EcoMenuBuilder(private val rows: Int) : MenuBuilder {
|
||||
private var title = "Menu"
|
||||
private var maskSlots: List<MutableList<Slot?>>
|
||||
private val components = mutableMapOf<Anchor, GUIComponent>()
|
||||
private val components = mutableMapOf<Anchor, MutableList<GUIComponent>>()
|
||||
private var onClose = CloseHandler { _, _ -> }
|
||||
private var onOpen = OpenHandler { _, _ -> }
|
||||
private var onRender: (Player, Menu) -> Unit = { _, _ -> }
|
||||
@@ -34,7 +30,9 @@ class EcoMenuBuilder(private val rows: Int) : MenuBuilder {
|
||||
require(column + component.columns - 1 <= 9) { "Component is too large to be placed here!" }
|
||||
require(row + component.rows - 1 <= getRows()) { "Component is too large to be placed here!" }
|
||||
|
||||
components[Anchor(row, column)] = component
|
||||
val anchor = Anchor(row, column)
|
||||
components.computeIfAbsent(anchor) { mutableListOf() } += component
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
@@ -43,11 +41,6 @@ class EcoMenuBuilder(private val rows: Int) : MenuBuilder {
|
||||
return this
|
||||
}
|
||||
|
||||
override fun setMask(mask: FillerMask): MenuBuilder {
|
||||
maskSlots = mask.mask
|
||||
return this
|
||||
}
|
||||
|
||||
override fun onClose(action: CloseHandler): MenuBuilder {
|
||||
onClose = action
|
||||
return this
|
||||
@@ -64,27 +57,28 @@ class EcoMenuBuilder(private val rows: Int) : MenuBuilder {
|
||||
}
|
||||
|
||||
override fun build(): Menu {
|
||||
val componentsAtPoints = mutableMapOf<Anchor, OffsetComponent>()
|
||||
val componentsAtPoints = mutableMapOf<Anchor, MutableList<OffsetComponent>>()
|
||||
|
||||
// 4 nested for loops? Shut up. Silence. Quiet.
|
||||
for (row in (1..rows)) {
|
||||
for (column in (1..9)) {
|
||||
for ((anchor, component) in components) {
|
||||
// Too far to the top / left to be in bounds
|
||||
if (anchor.row > row || anchor.column > column) {
|
||||
continue
|
||||
}
|
||||
for ((anchor, availableComponents) in components) {
|
||||
for (component in availableComponents) {
|
||||
// Too far to the top / left to be in bounds
|
||||
if (anchor.row > row || anchor.column > column) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Too far to the bottom / left to be in bounds
|
||||
if (row > anchor.row + component.rows - 1 || column > anchor.column + component.columns - 1) {
|
||||
continue
|
||||
}
|
||||
// Too far to the bottom / left to be in bounds
|
||||
if (row > anchor.row + component.rows - 1 || column > anchor.column + component.columns - 1) {
|
||||
continue
|
||||
}
|
||||
|
||||
val rowOffset = anchor.row - row
|
||||
val columnOffset = anchor.column - column
|
||||
val rowOffset = anchor.row - row
|
||||
val columnOffset = anchor.column - column
|
||||
|
||||
val slot = component.getSlotAt(rowOffset, columnOffset)
|
||||
if (slot != null) {
|
||||
componentsAtPoints[Anchor(row, column)] = OffsetComponent(
|
||||
val point = Anchor(row, column)
|
||||
componentsAtPoints.computeIfAbsent(point) { mutableListOf() } += OffsetComponent(
|
||||
component,
|
||||
rowOffset,
|
||||
columnOffset
|
||||
@@ -96,8 +90,4 @@ class EcoMenuBuilder(private val rows: Int) : MenuBuilder {
|
||||
|
||||
return EcoMenu(rows, componentsAtPoints, title, onClose, onRender, onOpen)
|
||||
}
|
||||
|
||||
init {
|
||||
maskSlots = ListUtils.create2DList(rows, 9)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,9 @@ package com.willfp.eco.internal.gui.slot
|
||||
|
||||
import com.willfp.eco.core.gui.slot.functional.SlotHandler
|
||||
import com.willfp.eco.core.gui.slot.functional.SlotProvider
|
||||
import com.willfp.eco.util.toSingletonList
|
||||
import org.bukkit.entity.Player
|
||||
import org.bukkit.event.inventory.ClickType
|
||||
|
||||
class EcoCaptiveSlot(
|
||||
provider: SlotProvider,
|
||||
@@ -10,11 +12,9 @@ class EcoCaptiveSlot(
|
||||
private val notCaptiveFor: (Player) -> Boolean
|
||||
) : EcoSlot(
|
||||
provider,
|
||||
captiveWithTest(notCaptiveFor),
|
||||
captiveWithTest(notCaptiveFor),
|
||||
captiveWithTest(notCaptiveFor),
|
||||
captiveWithTest(notCaptiveFor),
|
||||
captiveWithTest(notCaptiveFor),
|
||||
ClickType.values().associateWith {
|
||||
captiveWithTest(notCaptiveFor).toSingletonList()
|
||||
},
|
||||
{ _, _, prev -> prev }
|
||||
) {
|
||||
override fun isCaptive(): Boolean {
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
package com.willfp.eco.internal.gui.slot
|
||||
|
||||
import com.willfp.eco.core.gui.slot.functional.SlotHandler
|
||||
import org.bukkit.inventory.ItemStack
|
||||
|
||||
private val noop = SlotHandler { _, _, _ -> }
|
||||
|
||||
class EcoFillerSlot(itemStack: ItemStack) : EcoSlot(
|
||||
{ _, _ -> itemStack },
|
||||
noop,
|
||||
noop,
|
||||
noop,
|
||||
noop,
|
||||
noop,
|
||||
{ _, _, prev -> prev }
|
||||
)
|
||||
@@ -14,27 +14,19 @@ import org.bukkit.inventory.ItemStack
|
||||
|
||||
open class EcoSlot(
|
||||
private val provider: SlotProvider,
|
||||
private val onLeftClick: SlotHandler,
|
||||
private val onRightClick: SlotHandler,
|
||||
private val onShiftLeftClick: SlotHandler,
|
||||
private val onShiftRightClick: SlotHandler,
|
||||
private val onMiddleClick: SlotHandler,
|
||||
private val handlers: Map<ClickType, List<SlotHandler>>,
|
||||
private val updater: SlotUpdater
|
||||
) : Slot {
|
||||
private fun List<SlotHandler>.handle(event: InventoryClickEvent, slot: Slot, menu: Menu) =
|
||||
this.forEach { it.handle(event, slot, menu) }
|
||||
|
||||
fun handleInventoryClick(
|
||||
event: InventoryClickEvent,
|
||||
menu: Menu
|
||||
) {
|
||||
event.isCancelled = true
|
||||
|
||||
when (event.click) {
|
||||
ClickType.LEFT -> this.onLeftClick.handle(event, this, menu)
|
||||
ClickType.RIGHT -> this.onRightClick.handle(event, this, menu)
|
||||
ClickType.SHIFT_LEFT -> this.onShiftLeftClick.handle(event, this, menu)
|
||||
ClickType.SHIFT_RIGHT -> this.onShiftRightClick.handle(event, this, menu)
|
||||
ClickType.MIDDLE -> this.onMiddleClick.handle(event, this, menu)
|
||||
else -> {}
|
||||
}
|
||||
handlers[event.click]?.handle(event, this, menu)
|
||||
}
|
||||
|
||||
override fun getItemStack(player: Player): ItemStack {
|
||||
@@ -55,4 +47,4 @@ open class EcoSlot(
|
||||
override fun isCaptive(): Boolean {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,62 +1,25 @@
|
||||
package com.willfp.eco.internal.gui.slot
|
||||
|
||||
import com.willfp.eco.core.gui.menu.Menu
|
||||
import com.willfp.eco.core.gui.slot.Slot
|
||||
import com.willfp.eco.core.gui.slot.SlotBuilder
|
||||
import com.willfp.eco.core.gui.slot.functional.SlotHandler
|
||||
import com.willfp.eco.core.gui.slot.functional.SlotProvider
|
||||
import com.willfp.eco.core.gui.slot.functional.SlotUpdater
|
||||
import org.bukkit.entity.Player
|
||||
import org.bukkit.event.inventory.InventoryClickEvent
|
||||
import org.bukkit.event.inventory.ClickType
|
||||
import java.util.function.Predicate
|
||||
|
||||
internal object NoOpSlot : SlotHandler {
|
||||
override fun handle(event: InventoryClickEvent, slot: Slot, menu: Menu) {
|
||||
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
return other is NoOpSlot
|
||||
}
|
||||
}
|
||||
|
||||
internal class NoOpForPlayer
|
||||
|
||||
class EcoSlotBuilder(private val provider: SlotProvider) : SlotBuilder {
|
||||
private var captive = false
|
||||
private var captiveFromEmpty = false
|
||||
private var updater: SlotUpdater = SlotUpdater { player, menu, _ -> provider.provide(player, menu) }
|
||||
|
||||
private var onLeftClick: SlotHandler = NoOpSlot
|
||||
private var onRightClick: SlotHandler = NoOpSlot
|
||||
private var onShiftLeftClick: SlotHandler = NoOpSlot
|
||||
private var onShiftRightClick: SlotHandler = NoOpSlot
|
||||
private var onMiddleClick: SlotHandler = NoOpSlot
|
||||
private val handlers = mutableMapOf<ClickType, MutableList<SlotHandler>>()
|
||||
|
||||
private var notCaptiveFor: (Player) -> Boolean = { false }
|
||||
|
||||
override fun onLeftClick(action: SlotHandler): SlotBuilder {
|
||||
onLeftClick = action
|
||||
return this
|
||||
}
|
||||
|
||||
override fun onRightClick(action: SlotHandler): SlotBuilder {
|
||||
onRightClick = action
|
||||
return this
|
||||
}
|
||||
|
||||
override fun onShiftLeftClick(action: SlotHandler): SlotBuilder {
|
||||
onShiftLeftClick = action
|
||||
return this
|
||||
}
|
||||
|
||||
override fun onShiftRightClick(action: SlotHandler): SlotBuilder {
|
||||
onShiftRightClick = action
|
||||
return this
|
||||
}
|
||||
|
||||
override fun onMiddleClick(action: SlotHandler): SlotBuilder {
|
||||
onMiddleClick = action
|
||||
override fun onClick(type: ClickType, action: SlotHandler): SlotBuilder {
|
||||
handlers.computeIfAbsent(type) { mutableListOf() } += action
|
||||
return this
|
||||
}
|
||||
|
||||
@@ -86,11 +49,7 @@ class EcoSlotBuilder(private val provider: SlotProvider) : SlotBuilder {
|
||||
} else {
|
||||
EcoSlot(
|
||||
provider,
|
||||
onLeftClick,
|
||||
onRightClick,
|
||||
onShiftLeftClick,
|
||||
onShiftRightClick,
|
||||
onMiddleClick,
|
||||
handlers,
|
||||
updater
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user