From 5902d3c95544c689dc3d93655b59abeab23bbe9d Mon Sep 17 00:00:00 2001 From: jhqwqmc Date: Fri, 5 Dec 2025 02:46:10 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=B8=85=E7=90=86?= =?UTF-8?q?=E7=89=A9=E5=93=81=E5=87=BD=E6=95=B0=E5=92=8C=E7=89=A9=E5=93=81?= =?UTF-8?q?=E6=A0=8F=E5=AD=98=E5=9C=A8=E7=89=A9=E5=93=81=E6=9D=A1=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../papi/CheckItemExpansion.java | 7 +-- .../plugin/user/BukkitServerPlayer.java | 10 ++++ .../core/entity/player/Player.java | 2 + .../context/condition/CommonConditions.java | 1 + .../condition/InventoryHasItemCondition.java | 51 ++++++++++++++++++ .../plugin/context/event/EventConditions.java | 1 + .../plugin/context/event/EventFunctions.java | 1 + .../context/function/ClearItemFunction.java | 54 +++++++++++++++++++ .../context/function/CommonFunctions.java | 1 + 9 files changed, 122 insertions(+), 6 deletions(-) create mode 100644 core/src/main/java/net/momirealms/craftengine/core/plugin/context/condition/InventoryHasItemCondition.java create mode 100644 core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/ClearItemFunction.java 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"); } From e04d5c5572836a714b83f52992385039cc48c61a Mon Sep 17 00:00:00 2001 From: jhqwqmc Date: Fri, 5 Dec 2025 02:52:05 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E8=AF=AD=E8=A8=80=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common-files/src/main/resources/translations/en.yml | 2 ++ common-files/src/main/resources/translations/zh_cn.yml | 2 ++ .../plugin/context/condition/InventoryHasItemCondition.java | 2 +- .../core/plugin/context/function/ClearItemFunction.java | 2 +- 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/common-files/src/main/resources/translations/en.yml b/common-files/src/main/resources/translations/en.yml index b4b992ed4..5089cdfb1 100644 --- a/common-files/src/main/resources/translations/en.yml +++ b/common-files/src/main/resources/translations/en.yml @@ -170,6 +170,7 @@ warning.config.condition.is_null.missing_argument: "Issue found in file warning.config.condition.hand.missing_hand: "Issue found in file - The config '' is missing the required 'hand' argument for 'hand' condition." warning.config.condition.hand.invalid_hand: "Issue found in file - The config '' is using an invalid 'hand' argument '' for 'hand' condition. Allowed hand types: []" warning.config.condition.on_cooldown.missing_id: "Issue found in file - The config '' is missing the required 'id' argument for 'on_cooldown' condition." +warning.config.condition.inventory_has_item.missing_id: "Issue found in file - The config '' is missing the required 'id' argument for 'inventory_has_item' condition." warning.config.structure.not_section: "Issue found in file - The config '' is expected to be a config section while it's actually a(n) ''." warning.config.image.duplicate: "Issue found in file - Duplicated image ''. Please check if there is the same configuration in other files." warning.config.image.missing_height: "Issue found in file - The image '' is missing the required 'height' argument." @@ -543,6 +544,7 @@ warning.config.function.transform_block.missing_block: "Issue found in f warning.config.function.cycle_block_property.missing_property: "Issue found in file - The config '' is missing the required 'property' argument for 'cycle_block_property' function." warning.config.function.set_exp.missing_count: "Issue found in file - The config '' is missing the required 'count' argument for 'set_exp' function." warning.config.function.set_level.missing_count: "Issue found in file - The config '' is missing the required 'count' argument for 'set_level' function." +warning.config.function.clear_item.missing_id: "Issue found in file - The config '' is missing the required 'id' argument for 'clear_item' function." warning.config.selector.missing_type: "Issue found in file - The config '' is missing the required 'type' argument for selector." warning.config.selector.invalid_type: "Issue found in file - The config '' is using an invalid selector type ''." warning.config.selector.invalid_target: "Issue found in file - The config '' is using an invalid selector target ''." diff --git a/common-files/src/main/resources/translations/zh_cn.yml b/common-files/src/main/resources/translations/zh_cn.yml index 71fbf6f5e..bf82355f0 100644 --- a/common-files/src/main/resources/translations/zh_cn.yml +++ b/common-files/src/main/resources/translations/zh_cn.yml @@ -167,6 +167,7 @@ warning.config.condition.is_null.missing_argument: "在文件 warning.config.condition.hand.missing_hand: "在文件 发现问题 - 配置项 '' 缺少 'hand' 条件必需的 'hand' 参数" warning.config.condition.hand.invalid_hand: "在文件 发现问题 - 配置项 '' 使用了无效的 'hand' 参数 '' ('hand' 条件). 允许的手部类型: []" warning.config.condition.on_cooldown.missing_id: "在文件 发现问题 - 配置项 '' 缺少 'on_cooldown' 条件必需的 'id' 参数" +warning.config.condition.inventory_has_item.missing_id: "在文件 发现问题 - 配置项 '' 缺少 'inventory_has_item' 条件必需的 'id' 参数" warning.config.structure.not_section: "在文件 发现问题 - 配置项 '' 应为配置段落 但实际类型为 ''" warning.config.image.duplicate: "在文件 发现问题 - 重复的图片配置 '' 请检查其他文件中是否存在相同配置" warning.config.image.missing_height: "在文件 发现问题 - 图片 '' 缺少必需的 'height' 参数" @@ -535,6 +536,7 @@ warning.config.function.transform_block.missing_block: "在文件 在文件 发现问题 - 配置项 '' 缺少 'cycle_block_property' 函数所需的 'property' 参数" warning.config.function.set_exp.missing_count: "在文件 发现问题 - 配置项 '' 缺少 'set_exp' 函数所需的 'count' 参数" warning.config.function.set_level.missing_count: "在文件 发现问题 - 配置项 '' 缺少 'set_level' 函数所需的 'count' 参数" +warning.config.function.clear_item.missing_id: "在文件 发现问题 - 配置项 '' 缺少 'clear_item' 函数所需的 'id' 参数" warning.config.selector.missing_type: "在文件 发现问题 - 配置项 '' 缺少选择器必需的 'type' 参数" warning.config.selector.invalid_type: "在文件 发现问题 - 配置项 '' 使用了无效的选择器类型 ''" warning.config.selector.invalid_target: "在文件 发现问题 - 配置项 '' 使用了无效的选择器目标 ''" 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 index 3498ccd7f..4b849ab41 100644 --- 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 @@ -43,7 +43,7 @@ public class InventoryHasItemCondition implements Condition @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")); + Key itemId = Key.of(ResourceConfigUtils.requireNonEmptyStringOrThrow(ResourceConfigUtils.get(arguments, "id", "item"), "warning.config.condition.inventory_has_item.missing_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/function/ClearItemFunction.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/context/function/ClearItemFunction.java index 0be7887b5..578266f53 100644 --- 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 @@ -46,7 +46,7 @@ public class ClearItemFunction extends AbstractConditionalF @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")); + Key itemId = Key.of(ResourceConfigUtils.requireNonEmptyStringOrThrow(ResourceConfigUtils.get(arguments, "id", "item"), "warning.config.function.clear_item.missing_id")); NumberProvider count = NumberProviders.fromObject(arguments.getOrDefault("count", 1)); return new ClearItemFunction<>(getPredicates(arguments), itemId, count); }