package cn.infstar.magicgem.item; import de.tr7zw.changeme.nbtapi.NBT; import org.bukkit.ChatColor; import org.bukkit.Material; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import java.util.Locale; import java.util.Set; public final class ItemMatcher { private final ItemCodec codec; public ItemMatcher(ItemCodec codec) { this.codec = codec; } public boolean matches(ItemStack item, Set requirements) { if (item == null || item.getType().isAir()) return false; if (requirements.isEmpty()) return true; for (String requirement : requirements) { if (matches(item, requirement)) return true; } return false; } public boolean matches(ItemStack item, String rawRequirement) { if (item == null || item.getType().isAir()) return false; String requirement = rawRequirement.toUpperCase(Locale.ROOT); Material material = item.getType(); if (requirement.equals("NOTHING")) return false; if (requirement.equals("ALL") || requirement.equals("ANY")) return true; if (requirement.startsWith("LORE:")) return loreContains(item, rawRequirement.substring(5)); if (requirement.startsWith("NAME:")) { ItemMeta meta = item.getItemMeta(); return meta.hasDisplayName() && strip(meta.getDisplayName()).contains(strip(rawRequirement.substring(5))); } if (requirement.startsWith("GEM:")) { String expected = rawRequirement.substring(4); return codec.embedded(item).entrySet().stream().anyMatch(entry -> entry.getValue() > 0 && (expected.equalsIgnoreCase("ALL") || expected.equalsIgnoreCase("ANY") || entry.getKey().equalsIgnoreCase(expected))); } if (requirement.startsWith("NBT:")) { String[] parts = rawRequirement.substring(4).split(":", 2); return NBT.get(item, nbt -> { if (!nbt.hasTag(parts[0])) return false; return parts.length == 1 || nbt.getString(parts[0]).equals(parts[1]); }); } if (material.name().equals(requirement) || material.name().endsWith('_' + requirement)) return true; return switch (requirement) { case "ARMOR" -> material.name().endsWith("_HELMET") || material.name().endsWith("_CHESTPLATE") || material.name().endsWith("_LEGGINGS") || material.name().endsWith("_BOOTS") || material == Material.ELYTRA; case "WEAPON" -> material.name().endsWith("_SWORD") || material.name().endsWith("_AXE") || material == Material.BOW || material == Material.CROSSBOW || material == Material.TRIDENT || material == Material.MACE; case "TOOL" -> material.name().endsWith("_PICKAXE") || material.name().endsWith("_AXE") || material.name().endsWith("_SHOVEL") || material.name().endsWith("_HOE") || material == Material.SHEARS || material == Material.FISHING_ROD; case "HELMET", "HEAD" -> material.name().endsWith("_HELMET"); case "CHEST", "CHESTPLATE" -> material.name().endsWith("_CHESTPLATE") || material == Material.ELYTRA; case "LEGS", "LEGGINGS" -> material.name().endsWith("_LEGGINGS"); case "FEET", "BOOTS" -> material.name().endsWith("_BOOTS"); default -> false; }; } private boolean loreContains(ItemStack item, String expected) { ItemMeta meta = item.getItemMeta(); if (!meta.hasLore() || meta.getLore() == null) return false; String clean = strip(expected); return meta.getLore().stream().map(this::strip).anyMatch(line -> line.contains(clean)); } private String strip(String value) { return ChatColor.stripColor(ChatColor.translateAlternateColorCodes('&', value == null ? "" : value)); } }