diff --git a/eco-api/src/main/java/com/willfp/eco/core/gui/slot/CustomSlot.java b/eco-api/src/main/java/com/willfp/eco/core/gui/slot/CustomSlot.java index 6a85aefe..8ace01c0 100644 --- a/eco-api/src/main/java/com/willfp/eco/core/gui/slot/CustomSlot.java +++ b/eco-api/src/main/java/com/willfp/eco/core/gui/slot/CustomSlot.java @@ -4,6 +4,7 @@ import com.willfp.eco.core.gui.menu.Menu; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * Base class for custom slot implementations. @@ -49,6 +50,17 @@ public abstract class CustomSlot implements Slot { return delegate.isCaptive(player, menu); } + @Override + public boolean isCaptiveForItem(@NotNull final Player player, + @NotNull final Menu menu, + @Nullable final ItemStack item) { + if (delegate == null) { + throw new IllegalStateException("Custom Slot was not initialized!"); + } + + return delegate.isCaptiveForItem(player, menu, item); + } + @Override public boolean isCaptiveFromEmpty() { if (delegate == null) { diff --git a/eco-api/src/main/java/com/willfp/eco/core/gui/slot/ReactiveSlot.java b/eco-api/src/main/java/com/willfp/eco/core/gui/slot/ReactiveSlot.java index d0c87664..cc698f6b 100644 --- a/eco-api/src/main/java/com/willfp/eco/core/gui/slot/ReactiveSlot.java +++ b/eco-api/src/main/java/com/willfp/eco/core/gui/slot/ReactiveSlot.java @@ -5,6 +5,7 @@ import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * Base class for custom slot implementations. @@ -39,6 +40,13 @@ public abstract class ReactiveSlot implements Slot { return getSlot(player, menu).isCaptive(player, menu); } + @Override + public boolean isCaptiveForItem(@NotNull final Player player, + @NotNull final Menu menu, + @Nullable final ItemStack item) { + return getSlot(player, menu).isCaptiveForItem(player, menu, item); + } + @Override public final @NotNull Slot getActionableSlot(@NotNull final Player player, @NotNull final Menu menu) { diff --git a/eco-api/src/main/java/com/willfp/eco/core/gui/slot/Slot.java b/eco-api/src/main/java/com/willfp/eco/core/gui/slot/Slot.java index 0a0c9256..1e5d8a17 100644 --- a/eco-api/src/main/java/com/willfp/eco/core/gui/slot/Slot.java +++ b/eco-api/src/main/java/com/willfp/eco/core/gui/slot/Slot.java @@ -9,6 +9,7 @@ import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.function.Function; @@ -45,6 +46,20 @@ public interface Slot extends GUIComponent { return false; } + /** + * If the slot is captive for this item. (Can this item be placed in it). + * + * @param player The player. + * @param menu The menu. + * @param itemStack The item. + * @return If captive. + */ + default boolean isCaptiveForItem(@NotNull final Player player, + @NotNull final Menu menu, + @Nullable final ItemStack itemStack) { + return false; + } + /** * Get the actionable slot to be shown. *

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 2d46b5fe..ca5feba8 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 @@ -6,9 +6,12 @@ import com.willfp.eco.core.gui.slot.functional.SlotUpdater; import org.bukkit.entity.Player; import org.bukkit.event.inventory.ClickType; import org.bukkit.event.inventory.InventoryClickEvent; +import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.function.BiConsumer; +import java.util.function.BiPredicate; import java.util.function.Predicate; /** @@ -143,7 +146,15 @@ public interface SlotBuilder { * @param predicate The predicate. Returns true when the slot should not be captive. * @return The builder. */ - SlotBuilder notCaptiveFor(@NotNull Predicate predicate); + SlotBuilder notCaptiveFor(Predicate predicate); + + /** + * Prevent captive for players that match a predicate. + * + * @param predicate The predicate. Returns true when the slot should not be captive. + * @return The builder. + */ + SlotBuilder notCaptiveForItem(BiPredicate predicate); /** * Set the ItemStack updater. diff --git a/eco-api/src/main/kotlin/com/willfp/eco/core/gui/GUIHelpers.kt b/eco-api/src/main/kotlin/com/willfp/eco/core/gui/GUIHelpers.kt index fa37f528..2ce74786 100644 --- a/eco-api/src/main/kotlin/com/willfp/eco/core/gui/GUIHelpers.kt +++ b/eco-api/src/main/kotlin/com/willfp/eco/core/gui/GUIHelpers.kt @@ -74,6 +74,10 @@ fun SlotBuilder.onClick(clickType: ClickType, action: (Player, InventoryClickEve fun SlotBuilder.notCaptiveFor(test: (Player) -> Boolean): SlotBuilder = this.notCaptiveFor { test(it) } +/** @see SlotBuilder.notCaptiveFor */ +fun SlotBuilder.notCaptiveForItem(test: (Player, ItemStack?) -> Boolean): SlotBuilder = + this.notCaptiveForItem { player, item -> test(player, item) } + /** * @see SlotBuilder.setModifier * @deprecated Use SlotUpdater instead. diff --git a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/gui/slot/EcoCaptiveSlot.kt b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/gui/slot/EcoCaptiveSlot.kt index 8b014aff..75aa6483 100644 --- a/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/gui/slot/EcoCaptiveSlot.kt +++ b/eco-core/core-backend/src/main/kotlin/com/willfp/eco/internal/gui/slot/EcoCaptiveSlot.kt @@ -6,15 +6,17 @@ 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 +import org.bukkit.inventory.ItemStack class EcoCaptiveSlot( provider: SlotProvider, private val captiveFromEmpty: Boolean, - private val notCaptiveFor: (Player) -> Boolean + private val notCaptiveFor: (Player) -> Boolean, + private val notCaptiveForItem: (Player, ItemStack?) -> Boolean ) : EcoSlot( provider, ClickType.values().associateWith { - captiveWithTest(notCaptiveFor).toSingletonList() + captiveWithTest(notCaptiveFor, notCaptiveForItem).toSingletonList() }, { _, _, prev -> prev } ) { @@ -22,13 +24,18 @@ class EcoCaptiveSlot( return !notCaptiveFor(player) } + override fun isCaptiveForItem(player: Player, menu: Menu, itemStack: ItemStack?): Boolean { + return !notCaptiveForItem(player, itemStack) + } + override fun isCaptiveFromEmpty(): Boolean { return captiveFromEmpty } } -private fun captiveWithTest(test: (Player) -> Boolean): SlotHandler { +private fun captiveWithTest(test: (Player) -> Boolean, + itemTest: (Player, ItemStack?) -> Boolean): SlotHandler { return SlotHandler { event, _, _ -> - event.isCancelled = test(event.whoClicked as Player) + event.isCancelled = itemTest(event.whoClicked as Player, event.cursor) || test(event.whoClicked as Player) } } 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 07f82134..7d9e7d7b 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 @@ -7,6 +7,8 @@ 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.ClickType +import org.bukkit.inventory.ItemStack +import java.util.function.BiPredicate import java.util.function.Predicate class EcoSlotBuilder(private val provider: SlotProvider) : SlotBuilder { @@ -17,6 +19,7 @@ class EcoSlotBuilder(private val provider: SlotProvider) : SlotBuilder { private val handlers = mutableMapOf>() private var notCaptiveFor: (Player) -> Boolean = { false } + private var notCaptiveForItem: (Player, ItemStack?) -> Boolean = { _, _ -> false} override fun onClick(type: ClickType, action: SlotHandler): SlotBuilder { handlers.computeIfAbsent(type) { mutableListOf() } += action @@ -28,6 +31,17 @@ class EcoSlotBuilder(private val provider: SlotProvider) : SlotBuilder { return this } + /** + * Prevent captive for players that match a predicate. + * + * @param predicate The predicate. Returns true when the slot should not be captive. + * @return The builder. + */ + override fun notCaptiveForItem(predicate: BiPredicate): SlotBuilder { + notCaptiveForItem = { player, item -> predicate.test(player, item) } + return this + } + override fun setCaptive(fromEmpty: Boolean): SlotBuilder { captive = true captiveFromEmpty = fromEmpty @@ -44,7 +58,8 @@ class EcoSlotBuilder(private val provider: SlotProvider) : SlotBuilder { EcoCaptiveSlot( provider, captiveFromEmpty, - notCaptiveFor + notCaptiveFor, + notCaptiveForItem ) } else { EcoSlot( diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/EcoSpigotPlugin.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/EcoSpigotPlugin.kt index 9cb8ddbf..bd219305 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/EcoSpigotPlugin.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/EcoSpigotPlugin.kt @@ -87,7 +87,6 @@ import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefCombatLogX import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefCombatLogXV11 import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefCrashClaim import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefDeluxeCombat -import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefFabledSkyBlock import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefFactionsUUID import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefGriefPrevention import com.willfp.eco.internal.spigot.integrations.antigrief.AntigriefIridiumSkyblock @@ -263,7 +262,6 @@ abstract class EcoSpigotPlugin : EcoPlugin() { IntegrationLoader("IridiumSkyblock") { AntigriefManager.register(AntigriefIridiumSkyblock()) }, IntegrationLoader("DeluxeCombat") { AntigriefManager.register(AntigriefDeluxeCombat()) }, IntegrationLoader("SuperiorSkyblock2") { AntigriefManager.register(AntigriefSuperiorSkyblock2()) }, - IntegrationLoader("FabledSkyBlock") { AntigriefManager.register(AntigriefFabledSkyBlock()) }, IntegrationLoader("BentoBox") { AntigriefManager.register(AntigriefBentoBox()) }, IntegrationLoader("WorldGuard") { AntigriefManager.register(AntigriefWorldGuard()) }, IntegrationLoader("GriefPrevention") { AntigriefManager.register(AntigriefGriefPrevention()) }, diff --git a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/gui/GUIListener.kt b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/gui/GUIListener.kt index a09dd2ae..c425fd15 100644 --- a/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/gui/GUIListener.kt +++ b/eco-core/core-plugin/src/main/kotlin/com/willfp/eco/internal/spigot/gui/GUIListener.kt @@ -95,7 +95,7 @@ class GUIListener(private val plugin: EcoPlugin) : Listener { val slot = menu.getSlot(row, column, player) - if (!slot.isCaptive(player, menu)) { + if (!slot.isCaptive(player, menu) || !slot.isCaptiveForItem(player, menu, event.currentItem)) { event.isCancelled = true } }