Reworked GUI backend to be component-based
This commit is contained in:
@@ -3,7 +3,6 @@ package com.willfp.eco.core.gui.menu;
|
||||
import com.willfp.eco.core.gui.component.GUIComponent;
|
||||
import com.willfp.eco.core.gui.slot.FillerMask;
|
||||
import com.willfp.eco.core.gui.slot.Slot;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.inventory.InventoryCloseEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -38,9 +37,12 @@ public interface MenuBuilder {
|
||||
* @param slot The slot.
|
||||
* @return The builder.
|
||||
*/
|
||||
MenuBuilder setSlot(int row,
|
||||
int column,
|
||||
@NotNull Slot slot);
|
||||
default MenuBuilder setSlot(final int row,
|
||||
final int column,
|
||||
@NotNull final Slot slot) {
|
||||
return this.addComponent(row, column, slot);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a component.
|
||||
@@ -50,23 +52,9 @@ public interface MenuBuilder {
|
||||
* @param component The component.
|
||||
* @return The builder.
|
||||
*/
|
||||
default MenuBuilder addComponent(final int row,
|
||||
final int column,
|
||||
@NotNull GUIComponent component) {
|
||||
Validate.isTrue(column + component.getColumns() - 1 <= 9, "Component is too large to be placed here!");
|
||||
Validate.isTrue(row + component.getRows() - 1 <= this.getRows(), "Component is too large to be placed here!");
|
||||
|
||||
for (int currentRow = row; currentRow < row + component.getRows(); currentRow++) {
|
||||
for (int currentCol = column; currentCol < column + component.getColumns(); currentCol++) {
|
||||
Slot slot = component.getSlotAt(currentRow, currentCol);
|
||||
if (slot != null) {
|
||||
setSlot(currentRow, currentCol, slot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
MenuBuilder addComponent(int row,
|
||||
int column,
|
||||
@NotNull GUIComponent component);
|
||||
|
||||
/**
|
||||
* Run function to modify the builder.
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.willfp.eco.internal.gui.menu
|
||||
|
||||
data class Anchor(
|
||||
val row: Int,
|
||||
val column: Int
|
||||
)
|
||||
@@ -4,7 +4,7 @@ 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.Slot
|
||||
import com.willfp.eco.internal.gui.slot.EcoSlot
|
||||
import com.willfp.eco.internal.gui.slot.EmptyFillerSlot
|
||||
import com.willfp.eco.util.NamespacedKeyUtils
|
||||
import org.bukkit.Bukkit
|
||||
import org.bukkit.NamespacedKey
|
||||
@@ -17,41 +17,29 @@ import org.bukkit.persistence.PersistentDataType
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
class EcoMenu(
|
||||
private val rows: Int,
|
||||
val slots: List<MutableList<EcoSlot>>,
|
||||
private val slots: Map<Anchor, Slot>,
|
||||
private val title: String,
|
||||
private val onClose: CloseHandler,
|
||||
private val onRender: (Player, Menu) -> Unit,
|
||||
private val onOpen: OpenHandler
|
||||
) : Menu {
|
||||
override fun getSlot(row: Int, column: Int): Slot {
|
||||
if (row < 1 || row > this.rows) {
|
||||
return slots[0][0]
|
||||
if (row < 1 || row > this.rows || column < 1 || column > 9) {
|
||||
return EmptyFillerSlot
|
||||
}
|
||||
|
||||
if (column < 1 || column > 9) {
|
||||
return slots[0][0]
|
||||
}
|
||||
|
||||
return slots[row - 1][column - 1]
|
||||
return slots[Anchor(row, column)] ?: EmptyFillerSlot
|
||||
}
|
||||
|
||||
override fun open(player: Player): Inventory {
|
||||
val inventory = Bukkit.createInventory(null, rows * 9, title)
|
||||
|
||||
var i = 0
|
||||
for (row in slots) {
|
||||
for (slot in row) {
|
||||
if (i == rows * 9) {
|
||||
break
|
||||
}
|
||||
inventory.setItem(i, slot.getItemStack(player, this))
|
||||
i++
|
||||
}
|
||||
}
|
||||
inventory.asRenderedInventory()?.render(noSideEffects = true)
|
||||
|
||||
player.openInventory(inventory)
|
||||
MenuHandler.registerInventory(inventory, this, player)
|
||||
|
||||
onOpen.handle(player, this)
|
||||
|
||||
inventory.asRenderedInventory()?.generateCaptive()
|
||||
return inventory
|
||||
}
|
||||
|
||||
@@ -1,26 +1,22 @@
|
||||
package com.willfp.eco.internal.gui.menu
|
||||
|
||||
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.MenuBuilder
|
||||
import com.willfp.eco.core.gui.menu.OpenHandler
|
||||
import com.willfp.eco.core.gui.slot.FillerMask
|
||||
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.internal.gui.slot.EcoSlot
|
||||
import com.willfp.eco.util.ListUtils
|
||||
import com.willfp.eco.util.StringUtils
|
||||
import org.bukkit.Material
|
||||
import org.bukkit.entity.Player
|
||||
import org.bukkit.inventory.ItemStack
|
||||
import java.util.function.BiConsumer
|
||||
import java.util.function.Consumer
|
||||
|
||||
class EcoMenuBuilder(private val rows: Int) : MenuBuilder {
|
||||
private var title = "Menu"
|
||||
private var maskSlots: List<MutableList<Slot?>>
|
||||
private val slots: List<MutableList<Slot?>> = ListUtils.create2DList(rows, 9)
|
||||
private val components = mutableMapOf<Anchor, GUIComponent>()
|
||||
private var onClose = CloseHandler { _, _ -> }
|
||||
private var onOpen = OpenHandler { _, _ -> }
|
||||
private var onRender: (Player, Menu) -> Unit = { _, _ -> }
|
||||
@@ -32,14 +28,13 @@ class EcoMenuBuilder(private val rows: Int) : MenuBuilder {
|
||||
return this
|
||||
}
|
||||
|
||||
override fun setSlot(
|
||||
row: Int,
|
||||
column: Int,
|
||||
slot: Slot
|
||||
): MenuBuilder {
|
||||
override fun addComponent(row: Int, column: Int, component: GUIComponent): MenuBuilder {
|
||||
require(!(row < 1 || row > rows)) { "Invalid row number!" }
|
||||
require(!(column < 1 || column > 9)) { "Invalid column number!" }
|
||||
slots[row - 1][column - 1] = slot
|
||||
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
|
||||
return this
|
||||
}
|
||||
|
||||
@@ -69,30 +64,33 @@ class EcoMenuBuilder(private val rows: Int) : MenuBuilder {
|
||||
}
|
||||
|
||||
override fun build(): Menu {
|
||||
val tempSlots = mutableListOf<MutableList<Slot?>>()
|
||||
val slots = mutableMapOf<Anchor, Slot>()
|
||||
|
||||
for (i in slots.indices) {
|
||||
for (j in slots[i].indices) {
|
||||
val slot = slots[i][j] ?: continue
|
||||
tempSlots[i][j] = slot
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
val finalSlots = mutableListOf<MutableList<EcoSlot>>()
|
||||
// Too far to the bottom / left to be in bounds
|
||||
if (row > anchor.row + component.rows - 1 || column > anchor.column + component.columns - 1) {
|
||||
continue
|
||||
}
|
||||
|
||||
for (row in tempSlots) {
|
||||
val tempRow = mutableListOf<EcoSlot>()
|
||||
for (slot in row) {
|
||||
var tempSlot = slot
|
||||
if (tempSlot is FillerSlot) {
|
||||
tempSlot = EcoFillerSlot(tempSlot.itemStack)
|
||||
val rowOffset = anchor.row - row
|
||||
val columnOffset = anchor.column - column
|
||||
|
||||
val slot = component.getSlotAt(rowOffset, columnOffset)
|
||||
if (slot != null) {
|
||||
slots[Anchor(row, column)] = slot
|
||||
}
|
||||
}
|
||||
tempRow.add((tempSlot ?: EcoFillerSlot(ItemStack(Material.AIR))) as EcoSlot)
|
||||
}
|
||||
finalSlots.add(tempRow)
|
||||
}
|
||||
|
||||
return EcoMenu(rows, finalSlots, title, onClose, onRender, onOpen)
|
||||
return EcoMenu(rows, slots, title, onClose, onRender, onOpen)
|
||||
}
|
||||
|
||||
init {
|
||||
|
||||
@@ -13,25 +13,23 @@ class MenuRenderedInventory(
|
||||
val captiveItems = mutableListOf<ItemStack>()
|
||||
val state = mutableMapOf<String, Any?>()
|
||||
|
||||
fun render() {
|
||||
generateCaptive()
|
||||
fun render(noSideEffects: Boolean = false) {
|
||||
if (!noSideEffects) {
|
||||
generateCaptive()
|
||||
}
|
||||
|
||||
var i = 0
|
||||
for (row in menu.slots) {
|
||||
for (slot in row) {
|
||||
if (i == menu.rows * 9) {
|
||||
break
|
||||
}
|
||||
for (row in (1..menu.rows)) {
|
||||
for (column in (1..9)) {
|
||||
val bukkit = MenuUtils.rowColumnToSlot(row, column)
|
||||
val item = menu.getSlot(row, column).getItemStack(player)
|
||||
|
||||
if (!slot.isCaptive) {
|
||||
inventory.setItem(i, slot.getItemStack(player, menu))
|
||||
}
|
||||
|
||||
i++
|
||||
inventory.setItem(bukkit, item)
|
||||
}
|
||||
}
|
||||
|
||||
menu.runOnRender(player)
|
||||
if (!noSideEffects) {
|
||||
menu.runOnRender(player)
|
||||
}
|
||||
}
|
||||
|
||||
fun generateCaptive() {
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
package com.willfp.eco.internal.gui.slot
|
||||
|
||||
import org.bukkit.Material
|
||||
import org.bukkit.inventory.ItemStack
|
||||
|
||||
class EcoFillerSlot(itemStack: ItemStack) : EcoSlot(
|
||||
open class EcoFillerSlot(itemStack: ItemStack) : EcoSlot(
|
||||
{ _, _ -> itemStack },
|
||||
{ _, _, _ -> },
|
||||
{ _, _, _ -> },
|
||||
@@ -10,4 +11,6 @@ class EcoFillerSlot(itemStack: ItemStack) : EcoSlot(
|
||||
{ _, _, _ -> },
|
||||
{ _, _, _ -> },
|
||||
{ _, _, prev -> prev }
|
||||
)
|
||||
)
|
||||
|
||||
object EmptyFillerSlot : EcoFillerSlot(ItemStack(Material.AIR))
|
||||
|
||||
Reference in New Issue
Block a user