diff --git a/eco-api/src/main/java/com/willfp/eco/core/gui/menu/Menu.java b/eco-api/src/main/java/com/willfp/eco/core/gui/menu/Menu.java index 156f8173..9265a4f2 100644 --- a/eco-api/src/main/java/com/willfp/eco/core/gui/menu/Menu.java +++ b/eco-api/src/main/java/com/willfp/eco/core/gui/menu/Menu.java @@ -4,8 +4,11 @@ import com.willfp.eco.core.Eco; import com.willfp.eco.core.gui.slot.Slot; import org.bukkit.entity.Player; import org.bukkit.inventory.Inventory; +import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; +import java.util.List; + /** * GUI version of {@link Inventory}. *

@@ -44,6 +47,14 @@ public interface Menu { */ Inventory open(@NotNull Player player); + /** + * Get captive items. + * + * @param player The player. + * @return The items. + */ + List getCaptiveItems(@NotNull Player player); + /** * Create a builder with a given amount of rows. * diff --git a/eco-api/src/main/java/com/willfp/eco/core/gui/slot/SlotBuilder.java b/eco-api/src/main/java/com/willfp/eco/core/gui/slot/SlotBuilder.java index 267696c8..de8b4f8b 100644 --- a/eco-api/src/main/java/com/willfp/eco/core/gui/slot/SlotBuilder.java +++ b/eco-api/src/main/java/com/willfp/eco/core/gui/slot/SlotBuilder.java @@ -49,6 +49,13 @@ public interface SlotBuilder { */ SlotBuilder onMiddleClick(@NotNull BiConsumer action); + /** + * Set slot to be a captive slot. + * + * @return The builder. + */ + SlotBuilder setCaptive(); + /** * Build the slot. * diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/gui/menu/EcoMenu.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/gui/menu/EcoMenu.kt index ca157311..a0a4215b 100644 --- a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/gui/menu/EcoMenu.kt +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/gui/menu/EcoMenu.kt @@ -1,14 +1,13 @@ package com.willfp.eco.internal.gui.menu import com.willfp.eco.core.gui.menu.Menu -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.StringUtils import org.bukkit.Bukkit import org.bukkit.entity.Player import org.bukkit.event.inventory.InventoryCloseEvent import org.bukkit.inventory.Inventory +import org.bukkit.inventory.ItemStack import java.util.function.Consumer class EcoMenu( @@ -17,7 +16,6 @@ class EcoMenu( private val title: String, private val onClose: Consumer ): Menu { - override fun getSlot(row: Int, column: Int): Slot { if (row < 1 || row > this.rows) { throw IllegalArgumentException("Invalid row number!") @@ -27,14 +25,7 @@ class EcoMenu( throw IllegalArgumentException("Invalid column number!") } - val slot = slots[row - 1][column - 1] - if (slot is FillerSlot) { - slots[row - 1][column - 1] = EcoFillerSlot(slot.itemStack) - - return getSlot(row, column) - } - - return slot + return slots[row - 1][column - 1] } override fun open(player: Player): Inventory { @@ -77,4 +68,9 @@ class EcoMenu( override fun getTitle(): String { return title } + + override fun getCaptiveItems(player: Player): MutableList { + val inventory = MenuHandler.getExtendedInventory(player.openInventory.topInventory) + return inventory.captiveItems + } } \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/gui/menu/EcoMenuBuilder.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/gui/menu/EcoMenuBuilder.kt index 06d0703c..4cb6239e 100644 --- a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/gui/menu/EcoMenuBuilder.kt +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/gui/menu/EcoMenuBuilder.kt @@ -3,6 +3,7 @@ package com.willfp.eco.internal.gui.menu import com.willfp.eco.core.gui.menu.Menu import com.willfp.eco.core.gui.menu.MenuBuilder 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.util.ListUtils @@ -58,7 +59,10 @@ class EcoMenuBuilder(private val rows: Int) : MenuBuilder { for (i in slots.indices) { for (j in slots[i].indices) { - val slot = slots[i][j] + var slot = slots[i][j] + if (slot is FillerSlot) { + slot = EcoFillerSlot(slot.itemStack) + } finalSlots[i][j] = slot } } diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/gui/menu/ExtendedInventory.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/gui/menu/ExtendedInventory.kt new file mode 100644 index 00000000..c5e882ec --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/gui/menu/ExtendedInventory.kt @@ -0,0 +1,31 @@ +package com.willfp.eco.internal.gui.menu + +import com.willfp.eco.internal.gui.slot.EcoCaptivatorSlot +import com.willfp.eco.util.MenuUtils +import org.bukkit.entity.Player +import org.bukkit.inventory.Inventory +import org.bukkit.inventory.ItemStack + +class ExtendedInventory( + val inventory: Inventory, + private val menu: EcoMenu +) { + val captiveItems: MutableList = ArrayList() + + fun refresh(player: Player) { + captiveItems.clear() + for (i in 0 until inventory.size) { + val pair = MenuUtils.convertSlotToRowColumn(i); + val row = pair.first!! + val column = pair.second!! + val slot = menu.getSlot(row, column) + if (slot is EcoCaptivatorSlot) { + val defaultItem = slot.getItemStack(player) + val item = inventory.getItem(i) ?: continue + if (item != defaultItem) { + captiveItems.add(item) + } + } + } + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/gui/menu/MenuHandler.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/gui/menu/MenuHandler.kt index 6c217d2d..3491c5b2 100644 --- a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/gui/menu/MenuHandler.kt +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/gui/menu/MenuHandler.kt @@ -4,20 +4,28 @@ import com.willfp.eco.core.gui.menu.Menu import org.bukkit.inventory.Inventory object MenuHandler { - private val MENUS: MutableMap = HashMap() + private val MENUS: MutableMap = HashMap() + private val INVS: MutableMap = HashMap() fun registerMenu( inventory: Inventory, - menu: Menu + menu: EcoMenu ) { - MENUS[inventory] = menu + val extendedInventory = ExtendedInventory(inventory, menu) + INVS[inventory] = extendedInventory + MENUS[extendedInventory] = menu } fun unregisterMenu(inventory: Inventory) { - MENUS.remove(inventory) + MENUS.remove(INVS[inventory]) + INVS.remove(inventory) } fun getMenu(inventory: Inventory): Menu? { - return MENUS[inventory] + return MENUS[INVS[inventory]] + } + + fun getExtendedInventory(inventory: Inventory): ExtendedInventory { + return INVS[inventory]!! } } \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/gui/slot/EcoCaptivatorSlot.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/gui/slot/EcoCaptivatorSlot.kt new file mode 100644 index 00000000..bef92639 --- /dev/null +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/gui/slot/EcoCaptivatorSlot.kt @@ -0,0 +1,34 @@ +package com.willfp.eco.internal.gui.slot + +import com.willfp.eco.core.Eco +import com.willfp.eco.core.gui.slot.Slot +import org.bukkit.entity.Player +import org.bukkit.event.inventory.InventoryClickEvent +import org.bukkit.inventory.ItemStack +import java.util.function.BiConsumer +import java.util.function.Function + +class EcoCaptivatorSlot( + provider: Function +) : EcoSlot( + provider, + allowMovingItem, + allowMovingItem, + allowMovingItem, + allowMovingItem, + allowMovingItem +) { + var captive: ItemStack? = null + + override fun getItemStack(player: Player): ItemStack { + return captive ?: provider.apply(player); + } + + companion object { + val plugin = Eco.getHandler().ecoPlugin!! + + val allowMovingItem: BiConsumer = BiConsumer { event, _ -> + event.isCancelled = false + } + } +} \ No newline at end of file diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/gui/slot/EcoSlot.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/gui/slot/EcoSlot.kt index d5146fc4..a5a82054 100644 --- a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/gui/slot/EcoSlot.kt +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/gui/slot/EcoSlot.kt @@ -9,7 +9,7 @@ import java.util.function.BiConsumer import java.util.function.Function open class EcoSlot( - private val provider: Function, + val provider: Function, private val onLeftClick: BiConsumer, private val onRightClick: BiConsumer, private val onShiftLeftClick: BiConsumer, diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/gui/slot/EcoSlotBuilder.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/gui/slot/EcoSlotBuilder.kt index c4db620c..75261142 100644 --- a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/gui/slot/EcoSlotBuilder.kt +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/gui/slot/EcoSlotBuilder.kt @@ -9,6 +9,8 @@ import java.util.function.BiConsumer import java.util.function.Function class EcoSlotBuilder(private val provider: Function) : SlotBuilder { + private var captive = false; + private var onLeftClick: BiConsumer = BiConsumer { _, _ -> run { } } private var onRightClick: BiConsumer = BiConsumer { _, _ -> run { } } private var onShiftLeftClick: BiConsumer = BiConsumer { _, _ -> run { } } @@ -40,7 +42,16 @@ class EcoSlotBuilder(private val provider: Function) : SlotBu return this } + override fun setCaptive(): SlotBuilder { + captive = true + return this + } + override fun build(): Slot { - return EcoSlot(provider, onLeftClick, onRightClick, onShiftLeftClick, onShiftRightClick, onMiddleClick) + return if (captive) { + EcoCaptivatorSlot(provider) + } else { + EcoSlot(provider, onLeftClick, onRightClick, onShiftLeftClick, onShiftRightClick, onMiddleClick) + } } } \ No newline at end of file diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/spigot/gui/GUIListener.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/spigot/gui/GUIListener.kt index 1cbc6ab9..55c3a83e 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/spigot/gui/GUIListener.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/spigot/gui/GUIListener.kt @@ -2,13 +2,16 @@ package com.willfp.eco.spigot.gui import com.willfp.eco.core.EcoPlugin import com.willfp.eco.core.PluginDependent +import com.willfp.eco.core.drops.DropQueue import com.willfp.eco.internal.gui.menu.EcoMenu import com.willfp.eco.internal.gui.menu.MenuHandler import com.willfp.eco.internal.gui.slot.EcoSlot import com.willfp.eco.util.MenuUtils import org.apache.commons.lang.Validate +import org.bukkit.Bukkit import org.bukkit.entity.Player import org.bukkit.event.EventHandler +import org.bukkit.event.EventPriority import org.bukkit.event.Listener import org.bukkit.event.inventory.InventoryClickEvent import org.bukkit.event.inventory.InventoryCloseEvent @@ -16,13 +19,11 @@ import org.bukkit.event.inventory.InventoryCloseEvent class GUIListener(plugin: EcoPlugin) : PluginDependent(plugin), Listener { @EventHandler fun handleSlotClick(event: InventoryClickEvent) { - if (event.whoClicked !is Player) { + val player = event.whoClicked + if (player !is Player) { return } - if (event.clickedInventory == null) { - return - } - val menu = MenuHandler.getMenu(event.clickedInventory!!) ?: return + val menu = MenuHandler.getMenu(event.clickedInventory ?: return) ?: return val rowColumn = MenuUtils.convertSlotToRowColumn(event.slot) val row = rowColumn.first!! val column = rowColumn.second!! @@ -31,17 +32,40 @@ class GUIListener(plugin: EcoPlugin) : PluginDependent(plugin), Liste val ecoSlot = menu.getSlot(row, column) as EcoSlot event.isCancelled = true ecoSlot.handleInventoryClick(event) + + plugin.scheduler.run{ MenuHandler.getExtendedInventory(event.clickedInventory!!).refresh(player) } } @EventHandler + fun handleCaptivatorSlots(event: InventoryClickEvent) { + val player = event.whoClicked + if (player !is Player) { + return + } + + val menu = MenuHandler.getMenu(player.openInventory.topInventory) ?: return + + plugin.scheduler.run{ MenuHandler.getExtendedInventory(player.openInventory.topInventory).refresh(player) } + plugin.scheduler.runLater({ Bukkit.getLogger().info(menu.getCaptiveItems(player).toString()) }, 1) + } + + @EventHandler(priority = EventPriority.HIGH) fun handleClose(event: InventoryCloseEvent) { - if (event.player !is Player) { + val player = event.player + if (player !is Player) { return } val menu = MenuHandler.getMenu(event.inventory) ?: return Validate.isTrue(menu is EcoMenu, "Menu not instance of EcoMenu!") val ecoMenu = menu as EcoMenu ecoMenu.handleClose(event) + + DropQueue(player) + .addItems(ecoMenu.getCaptiveItems(player)) + .setLocation(player.location) + .forceTelekinesis() + .push() + plugin.scheduler.run { MenuHandler.unregisterMenu(event.inventory) } } } \ No newline at end of file