diff --git a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/papi/CheckItemExpansion.java b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/papi/CheckItemExpansion.java index a208e2901..f86fc0dbd 100644 --- a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/papi/CheckItemExpansion.java +++ b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/papi/CheckItemExpansion.java @@ -108,11 +108,6 @@ public class CheckItemExpansion extends PlaceholderExpansion { } private int getItemCount(BukkitServerPlayer player, String[] param) { - Key itemId = Key.of(param[0], param[1]); - Predicate predicate = nmsStack -> this.plugin.itemManager().wrap(ItemStackUtils.asCraftMirror(nmsStack)).id().equals(itemId); - Object inventory = FastNMS.INSTANCE.method$Player$getInventory(player.serverPlayer()); - Object inventoryMenu = FastNMS.INSTANCE.field$Player$inventoryMenu(player.serverPlayer()); - Object craftSlots = FastNMS.INSTANCE.method$InventoryMenu$getCraftSlots(inventoryMenu); - return FastNMS.INSTANCE.method$Inventory$clearOrCountMatchingItems(inventory, predicate, 0, craftSlots); + return player.clearOrCountMatchingInventoryItems(Key.of(param[0], param[1]), 0); } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java index 2bc3a8635..0358696d1 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java @@ -75,6 +75,7 @@ import java.lang.ref.Reference; import java.lang.ref.WeakReference; import java.util.*; import java.util.concurrent.ConcurrentHashMap; +import java.util.function.Predicate; public class BukkitServerPlayer extends Player { public static final Key SELECTED_LOCALE_KEY = Key.of("craftengine:locale"); @@ -1492,6 +1493,15 @@ public class BukkitServerPlayer extends Player { this.trackedBlockEntityRenderers.clear(); } + @Override + public int clearOrCountMatchingInventoryItems(Key itemId, int count) { + Predicate predicate = nmsStack -> this.plugin.itemManager().wrap(ItemStackUtils.asCraftMirror(nmsStack)).id().equals(itemId); + Object inventory = FastNMS.INSTANCE.method$Player$getInventory(serverPlayer()); + Object inventoryMenu = FastNMS.INSTANCE.field$Player$inventoryMenu(serverPlayer()); + Object craftSlots = FastNMS.INSTANCE.method$InventoryMenu$getCraftSlots(inventoryMenu); + return FastNMS.INSTANCE.method$Inventory$clearOrCountMatchingItems(inventory, predicate, count, craftSlots); + } + @Override public void addTrackedFurniture(int entityId, Furniture furniture) { this.trackedFurniture.put(entityId, new VirtualCullableObject(furniture)); diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/player/Player.java b/core/src/main/java/net/momirealms/craftengine/core/entity/player/Player.java index 6fd240dbb..b8792bde0 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/player/Player.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/player/Player.java @@ -226,6 +226,8 @@ public abstract class Player extends AbstractEntity implements NetWorkUser { public abstract void clearTrackedBlockEntities(); + public abstract int clearOrCountMatchingInventoryItems(Key itemId, int count); + @Override public void remove() { } diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/CommonConditions.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/CommonConditions.java index 991ea9e0a..16c0c5d22 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/CommonConditions.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/CommonConditions.java @@ -31,4 +31,5 @@ public final class CommonConditions { public static final Key IS_NULL = Key.from("craftengine:is_null"); public static final Key HAND = Key.from("craftengine:hand"); public static final Key HAS_PLAYER = Key.from("craftengine:has_player"); + public static final Key INVENTORY_HAS_ITEM = Key.from("craftengine:inventory_has_item"); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/InventoryHasItemCondition.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/InventoryHasItemCondition.java new file mode 100644 index 000000000..3498ccd7f --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/InventoryHasItemCondition.java @@ -0,0 +1,51 @@ +package net.momirealms.craftengine.core.plugin.context.condition; + +import net.momirealms.craftengine.core.entity.player.Player; +import net.momirealms.craftengine.core.item.Item; +import net.momirealms.craftengine.core.plugin.context.Condition; +import net.momirealms.craftengine.core.plugin.context.Context; +import net.momirealms.craftengine.core.plugin.context.number.NumberProvider; +import net.momirealms.craftengine.core.plugin.context.number.NumberProviders; +import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters; +import net.momirealms.craftengine.core.util.ItemUtils; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.ResourceConfigUtils; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; +import java.util.Optional; + +public class InventoryHasItemCondition implements Condition { + private final Key itemId; + private final NumberProvider count; + + public InventoryHasItemCondition(Key itemId, NumberProvider count) { + this.itemId = itemId; + this.count = count; + } + + @Override + public Key type() { + return CommonConditions.INVENTORY_HAS_ITEM; + } + + @Override + public boolean test(CTX ctx) { + Optional optionalPlayer = ctx.getOptionalParameter(DirectContextParameters.PLAYER); + if (optionalPlayer.isEmpty()) { + return false; + } + Player player = optionalPlayer.get(); + return player.clearOrCountMatchingInventoryItems(this.itemId, 0) >= this.count.getInt(ctx); + } + + public static class FactoryImpl implements ConditionFactory { + + @Override + public Condition create(Map arguments) { + Key itemId = Key.of(ResourceConfigUtils.requireNonEmptyStringOrThrow(ResourceConfigUtils.get(arguments, "id", "item"), "warning.config.condition.inventory_has_item.missing_item_id")); + NumberProvider count = NumberProviders.fromObject(arguments.getOrDefault("count", 1)); + return new InventoryHasItemCondition<>(itemId, count); + } + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventConditions.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventConditions.java index b17921ed4..6d2aa4996 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventConditions.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventConditions.java @@ -40,6 +40,7 @@ public class EventConditions { register(CommonConditions.IS_NULL, new IsNullCondition.FactoryImpl<>()); register(CommonConditions.HAND, new HandCondition.FactoryImpl<>()); register(CommonConditions.ON_COOLDOWN, new OnCooldownCondition.FactoryImpl<>()); + register(CommonConditions.INVENTORY_HAS_ITEM, new InventoryHasItemCondition.FactoryImpl<>()); } public static void register(Key key, ConditionFactory factory) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventFunctions.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventFunctions.java index fbc8a4e69..19bb76b41 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventFunctions.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/event/EventFunctions.java @@ -58,6 +58,7 @@ public class EventFunctions { register(CommonFunctions.SET_EXP, new SetExpFunction.FactoryImpl<>(EventConditions::fromMap)); register(CommonFunctions.SET_LEVEL, new SetLevelFunction.FactoryImpl<>(EventConditions::fromMap)); register(CommonFunctions.PLAY_TOTEM_ANIMATION, new PlayTotemAnimationFunction.FactoryImpl<>(EventConditions::fromMap)); + register(CommonFunctions.CLEAR_ITEM, new ClearItemFunction.FactoryImpl<>(EventConditions::fromMap)); } public static void register(Key key, FunctionFactory factory) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/ClearItemFunction.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/ClearItemFunction.java new file mode 100644 index 000000000..0be7887b5 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/ClearItemFunction.java @@ -0,0 +1,54 @@ +package net.momirealms.craftengine.core.plugin.context.function; + +import net.momirealms.craftengine.core.entity.player.Player; +import net.momirealms.craftengine.core.plugin.context.Condition; +import net.momirealms.craftengine.core.plugin.context.Context; +import net.momirealms.craftengine.core.plugin.context.number.NumberProvider; +import net.momirealms.craftengine.core.plugin.context.number.NumberProviders; +import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.ResourceConfigUtils; + +import java.util.List; +import java.util.Map; +import java.util.Optional; + +public class ClearItemFunction extends AbstractConditionalFunction { + private final Key itemId; + private final NumberProvider count; + + public ClearItemFunction(List> predicates, Key itemId, NumberProvider count) { + super(predicates); + this.itemId = itemId; + this.count = count; + } + + @Override + protected void runInternal(CTX ctx) { + Optional optionalPlayer = ctx.getOptionalParameter(DirectContextParameters.PLAYER); + if (optionalPlayer.isEmpty()) { + return; + } + Player player = optionalPlayer.get(); + player.clearOrCountMatchingInventoryItems(itemId, count.getInt(ctx)); + } + + @Override + public Key type() { + return CommonFunctions.CLEAR_ITEM; + } + + public static class FactoryImpl extends AbstractFactory { + + public FactoryImpl(java.util.function.Function, Condition> factory) { + super(factory); + } + + @Override + public Function create(Map arguments) { + Key itemId = Key.of(ResourceConfigUtils.requireNonEmptyStringOrThrow(ResourceConfigUtils.get(arguments, "id", "item"), "warning.config.function.clear_item.missing_item_id")); + NumberProvider count = NumberProviders.fromObject(arguments.getOrDefault("count", 1)); + return new ClearItemFunction<>(getPredicates(arguments), itemId, count); + } + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CommonFunctions.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CommonFunctions.java index 937534105..ccb288010 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CommonFunctions.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/CommonFunctions.java @@ -49,4 +49,5 @@ public final class CommonFunctions { public static final Key SET_EXP = Key.of("craftengine:set_exp"); public static final Key SET_LEVEL = Key.of("craftengine:set_level"); public static final Key PLAY_TOTEM_ANIMATION = Key.of("craftengine:play_totem_animation"); + public static final Key CLEAR_ITEM = Key.of("craftengine:clear_item"); }