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 new file mode 100644 index 000000000..e376c2f77 --- /dev/null +++ b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/papi/CheckItemExpansion.java @@ -0,0 +1,125 @@ +package net.momirealms.craftengine.bukkit.compatibility.papi; + +import me.clip.placeholderapi.expansion.PlaceholderExpansion; +import net.momirealms.craftengine.bukkit.item.BukkitItemManager; +import net.momirealms.craftengine.bukkit.nms.FastNMS; +import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; +import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer; +import net.momirealms.craftengine.bukkit.util.ItemStackUtils; +import net.momirealms.craftengine.core.entity.player.InteractionHand; +import net.momirealms.craftengine.core.item.Item; +import net.momirealms.craftengine.core.plugin.CraftEngine; +import net.momirealms.craftengine.core.util.Key; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Locale; +import java.util.function.Predicate; + +public class CheckItemExpansion extends PlaceholderExpansion { + private final CraftEngine plugin; + + public CheckItemExpansion(CraftEngine plugin) { + this.plugin = plugin; + } + + @NotNull + @Override + public String getIdentifier() { + return "checkceitem"; + } + + @NotNull + @Override + public String getAuthor() { + return "jhqwqmc"; + } + + @NotNull + @Override + public String getVersion() { + return "1.0"; + } + + @Override + public boolean persist() { + return true; + } + + /** + * 用法:(小括号括起来的为必填,中括号括起来的为选填) + *
+ * %checkceitem_count_(namespace):(path)% + *
+ * %checkceitem_has_(namespace):(path):[amount]% + *
+ * %checkceitem_id_[main_hand/off_hand/slot]% + *
+ * %checkceitem_iscustom_[main_hand/off_hand/slot]% + */ + @Override + public @Nullable String onPlaceholderRequest(Player bukkitPlayer, @NotNull String params) { + if (bukkitPlayer == null) return null; + BukkitServerPlayer player = BukkitCraftEngine.instance().adapt(bukkitPlayer); + if (player == null) return null; + int index = params.indexOf('_'); + String action = index > 0 ? params.substring(0, index) : params; + String[] param = index > 0 ? params.substring(index + 1).split(":", 3) : new String[0]; + return switch (action) { + case "count" -> param.length < 2 ? null : String.valueOf(getItemCount(player, param)); + case "has" -> { + if (param.length < 2) yield null; + int requiredAmount; + try { + requiredAmount = param.length < 3 ? 1 : Integer.parseInt(param[2]); + } catch (NumberFormatException e) { + this.plugin.logger().warn("Invalid amount: " + param[2], e); + yield null; + } + if (requiredAmount < 1) yield "true"; + yield String.valueOf(getItemCount(player, param) >= requiredAmount); + } + case "id" -> { + Item item = getItem(player, param); + if (item == null) yield null; + yield item.id().asString(); + } + case "iscustom" -> { + Item item = getItem(player, param); + if (item == null) yield null; + yield String.valueOf(item.isCustomItem()); + } + default -> null; + }; + } + + @Nullable + private Item getItem(BukkitServerPlayer player, String[] param) { + if (param.length < 1 || param[0] == null || param[0].isEmpty()) { + return player.getItemInHand(InteractionHand.MAIN_HAND); + } + return switch (param[0].toLowerCase(Locale.ROOT)) { + case "main_hand" -> player.getItemInHand(InteractionHand.MAIN_HAND); + case "off_hand" -> player.getItemInHand(InteractionHand.OFF_HAND); + default -> { + try { + int slot = Integer.parseInt(param[0]); + yield player.getItemBySlot(Math.max(slot, 0)); + } catch (NumberFormatException | ArrayIndexOutOfBoundsException e) { + this.plugin.logger().warn("Invalid slot: " + param[0], e); + yield null; + } + } + }; + } + + private int getItemCount(BukkitServerPlayer player, String[] param) { + Key itemId = Key.of(param[0], param[1]); + Predicate predicate = nmsStack -> BukkitItemManager.instance().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); + } +} diff --git a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/papi/PlaceholderAPIUtils.java b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/papi/PlaceholderAPIUtils.java index e96cb46dc..9f4dce361 100644 --- a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/papi/PlaceholderAPIUtils.java +++ b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/papi/PlaceholderAPIUtils.java @@ -20,5 +20,6 @@ public class PlaceholderAPIUtils { public static void registerExpansions(CraftEngine plugin) { new ImageExpansion(plugin).register(); new ShiftExpansion(plugin).register(); + new CheckItemExpansion(plugin).register(); } } diff --git a/bukkit/paper-loader/build.gradle.kts b/bukkit/paper-loader/build.gradle.kts index 9adc91209..17432d821 100644 --- a/bukkit/paper-loader/build.gradle.kts +++ b/bukkit/paper-loader/build.gradle.kts @@ -6,7 +6,7 @@ import java.net.URI plugins { id("com.gradleup.shadow") version "9.2.2" id("de.eldoria.plugin-yml.paper") version "0.7.1" - id("xyz.jpenilla.run-paper") version "2.3.1" + id("xyz.jpenilla.run-paper") version "3.0.2" } repositories { 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 3487d233f..af6789fab 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 @@ -946,6 +946,13 @@ public class BukkitServerPlayer extends Player { return BukkitItemManager.instance().wrap(hand == InteractionHand.MAIN_HAND ? inventory.getItemInMainHand() : inventory.getItemInOffHand()); } + @NotNull + @Override + public Item getItemBySlot(int slot) { + PlayerInventory inventory = platformPlayer().getInventory(); + return BukkitItemManager.instance().wrap(inventory.getItem(slot)); + } + @Override public World world() { return new BukkitWorld(platformPlayer().getWorld()); 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 82ad30715..c8088ef4f 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 @@ -26,6 +26,9 @@ public abstract class Player extends AbstractEntity implements NetWorkUser { @NotNull public abstract Item getItemInHand(InteractionHand hand); + @NotNull + public abstract Item getItemBySlot(int slot); + @Override public abstract Object platformPlayer();