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
}
}