Add ItemMatcher.java

This commit is contained in:
Len 2025-12-26 00:14:22 +01:00
parent f80408502b
commit b4cca9227e

View File

@ -0,0 +1,335 @@
package com.alttd.playershops.utils;
import org.bukkit.attribute.Attribute;
import org.bukkit.block.BlockState;
import org.bukkit.block.ShulkerBox;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.*;
import org.bukkit.map.MapView;
import org.bukkit.potion.PotionEffect;
import java.util.*;
public class ItemMatcher {
private final static List<Matcher> matcherList = new ArrayList<>();
static {
// DisplayName
matcherList.add(
(meta1, meta2) ->
Objects.equals(meta1.displayName(), meta2.displayName())
);
// Damage
matcherList.add(
(meta1, meta2) -> {
if (meta1 instanceof Damageable damageable1 && meta2 instanceof Damageable damageable2) {
return damageable1.getDamage() == damageable2.getDamage();
}
return true;
}
);
// Enchants
matcherList.add(
(meta1, meta2) -> {
if (meta1.hasEnchants() != meta2.hasEnchants()) {
return false;
}
if (meta1.hasEnchants()) {
final Map<Enchantment, Integer> enchants1 = meta1.getEnchants();
final Map<Enchantment, Integer> enchants2 = meta2.getEnchants();
return listMatches(enchants1.entrySet(), enchants2.entrySet());
}
return true;
}
);
// Potions
matcherList.add(
(meta1, meta2) -> {
if (meta1 instanceof PotionMeta potion1 && meta2 instanceof PotionMeta potion2) {
if (potion1.hasColor() != potion2.hasColor()) {
return false;
}
if (potion1.hasColor() && !Objects.equals(potion1.getColor(), potion2.getColor())) {
return false;
}
if (potion1.hasCustomEffects() != potion2.hasCustomEffects()) {
return false;
}
if (potion1.hasCustomEffects() && !Arrays.deepEquals(potion1.getCustomEffects().toArray(), potion2.getCustomEffects().toArray())) {
return false;
}
if (potion1.getBasePotionType() != null && potion2.getBasePotionType() != null) {
List<PotionEffect> effects1 = new ArrayList<>();
List<PotionEffect> effects2 = new ArrayList<>();
if (potion1.getBasePotionType() != null) {
effects1.addAll(potion1.getBasePotionType().getPotionEffects());
}
if (potion1.hasCustomEffects()) {
effects1.addAll(potion1.getCustomEffects());
}
if (potion2.getBasePotionType() != null) {
effects2.addAll(potion2.getBasePotionType().getPotionEffects());
}
if (potion2.hasCustomEffects()) {
effects2.addAll(potion2.getCustomEffects());
}
return listMatches(effects1, effects2);
}
}
return true;
}
);
// Attributes
matcherList.add(
(meta1, meta2) -> {
if (meta1.hasAttributeModifiers() != meta2.hasAttributeModifiers()) {
return false;
}
if (meta1.hasAttributeModifiers() && meta2.hasAttributeModifiers()) {
final Set<Attribute> set1 = Objects.requireNonNull(meta1.getAttributeModifiers()).keySet();
final Set<Attribute> set2 = Objects.requireNonNull(meta2.getAttributeModifiers()).keySet();
for(final Attribute att : set1) {
if(!set2.contains(att)) {
return false;
} else if(!meta1.getAttributeModifiers().get(att).equals(meta2.getAttributeModifiers().get(att))) {
return false;
}
}
}
return true;
}
);
// Itemflags
matcherList.add(
(meta1, meta2) -> {
return Arrays.deepEquals(meta1.getItemFlags().toArray(), meta2.getItemFlags().toArray());
}
);
// Books
matcherList.add(
(meta1, meta2) -> {
if (meta1 instanceof BookMeta bookMeta1 && meta2 instanceof BookMeta bookMeta2) {
if (bookMeta1.hasTitle() != bookMeta2.hasTitle()) {
return false;
}
if (bookMeta1.hasTitle() && !Objects.equals(bookMeta1.getTitle(), bookMeta2.getTitle())) {
return false;
}
if (bookMeta1.hasPages() != bookMeta2.hasPages()) {
return false;
}
if (bookMeta1.hasPages() && !bookMeta1.getPages().equals(bookMeta2.getPages())) {
return false;
}
if (bookMeta1.hasAuthor() != bookMeta2.hasAuthor()) {
return false;
}
if (bookMeta1.hasAuthor() && !Objects.equals(bookMeta1.getAuthor(), bookMeta2.getAuthor())) {
return false;
}
if (bookMeta1.hasGeneration() != bookMeta2.hasGeneration()) {
return false;
}
return !bookMeta1.hasGeneration() || Objects.equals(bookMeta1.getGeneration(), bookMeta2.getGeneration());
}
return true;
}
);
// Fireworks
matcherList.add(
(meta1, meta2) -> {
if (meta1 instanceof FireworkMeta fireworkMeta1 && meta2 instanceof FireworkMeta fireworkMeta2) {
if (fireworkMeta1.hasEffects() != fireworkMeta2.hasEffects()) {
return false;
}
if (!fireworkMeta1.getEffects().equals(fireworkMeta2.getEffects())) {
return false;
}
return fireworkMeta1.getPower() == fireworkMeta2.getPower();
}
return true;
}
);
// Banners
matcherList.add(
(meta1, meta2) -> {
if (meta1 instanceof BannerMeta bannerMeta1 && meta2 instanceof BannerMeta bannerMeta2) {
if (bannerMeta1.numberOfPatterns() != bannerMeta2.numberOfPatterns()) {
return false;
}
return new HashSet<>(bannerMeta1.getPatterns()).containsAll(bannerMeta2.getPatterns());
}
return true;
}
);
// Skulls/heads
matcherList.add(
(meta1, meta2) -> {
if (meta1 instanceof SkullMeta skullMeta1 && meta2 instanceof SkullMeta skullMeta2) {
return Objects.equals(skullMeta1.getOwningPlayer(), skullMeta2.getOwningPlayer());
}
return true;
}
);
// Bundles
matcherList.add(
(meta1, meta2) -> {
if (meta1 instanceof BundleMeta bundleMeta1 && meta2 instanceof BundleMeta bundleMeta2) {
if (bundleMeta1.hasItems() != bundleMeta2.hasItems()) {
return false;
}
if (bundleMeta1.hasItems()) {
return listMatches(bundleMeta1.getItems(), bundleMeta2.getItems());
}
}
return true;
}
);
// Maps
matcherList.add(
(meta1, meta2) -> {
if (meta1 instanceof MapMeta mapMeta1 && meta2 instanceof MapMeta mapMeta2) {
if (mapMeta1.hasMapView() != mapMeta2.hasMapView()) {
return false;
}
// TODO -- do we need checks on color?
// mapMeta1.getColor()
MapView mapView1 = mapMeta1.getMapView();
MapView mapView2 = mapMeta2.getMapView();
if (mapView1 == null || mapView2 == null)
return false;
if (mapView1.getId() == mapView2.getId())
return true;
}
return true;
}
);
// Leather
matcherList.add(
(meta1, meta2) -> {
if (meta1 instanceof LeatherArmorMeta leatherArmorMeta1 && meta2 instanceof LeatherArmorMeta leatherArmorMeta2) {
return leatherArmorMeta1.getColor().equals(leatherArmorMeta2.getColor());
}
return true;
}
);
// Tropical fishes
matcherList.add(
(meta1, meta2) -> {
if (meta1 instanceof TropicalFishBucketMeta tropicalFishBucketMeta1 && meta2 instanceof TropicalFishBucketMeta tropicalFishBucketMeta2) {
if (tropicalFishBucketMeta1.hasVariant() != tropicalFishBucketMeta2.hasVariant()) {
return false;
}
return !tropicalFishBucketMeta1.hasVariant()
|| (tropicalFishBucketMeta1.getPattern() == tropicalFishBucketMeta2.getPattern()
&& tropicalFishBucketMeta1.getBodyColor().equals(tropicalFishBucketMeta2.getBodyColor())
&& tropicalFishBucketMeta1.getPatternColor().equals(tropicalFishBucketMeta2.getPatternColor()));
}
return true;
}
);
// Axolotls
matcherList.add(
(meta1, meta2) -> {
if (meta1 instanceof AxolotlBucketMeta axolotlBucketMeta1 && meta2 instanceof AxolotlBucketMeta axolotlBucketMeta2) {
return axolotlBucketMeta1.getVariant() == axolotlBucketMeta2.getVariant();
}
return true;
}
);
// Shulkerboxes
matcherList.add(
(meta1, meta2) -> {
if (meta1 instanceof BlockStateMeta blockStateMeta1 && meta2 instanceof BlockStateMeta blockStateMeta2) {
// extra heavy - Banners, Shulkerboxes, beehive and more?
BlockState blockState1 = blockStateMeta1.getBlockState();
BlockState blockState2 = blockStateMeta2.getBlockState();
if (blockState1 instanceof ShulkerBox shulkerBox1 && blockState2 instanceof ShulkerBox shulkerBox2) {
if (shulkerBox1.getColor() != shulkerBox2.getColor())
return false; // not the same color
// Do we need all of the above checks inside the shulker?
if (Arrays.equals(shulkerBox1.getInventory().getContents(), shulkerBox2.getInventory().getContents()))
return true; // same content
}
}
return true;
}
);
// Suspicious stews
matcherList.add(
(meta1, meta2) -> {
if (meta1 instanceof SuspiciousStewMeta suspiciousStewMeta1 && meta2 instanceof SuspiciousStewMeta suspiciousStewMeta2) {
if (suspiciousStewMeta1.hasCustomEffects() != suspiciousStewMeta2.hasCustomEffects()) {
return false;
}
if (suspiciousStewMeta1.hasCustomEffects()) {
return listMatches(suspiciousStewMeta1.getCustomEffects(), suspiciousStewMeta2.getCustomEffects());
}
}
return true;
}
);
}
public static boolean matches(ItemStack item1, ItemStack item2) {
if (item1 == null && item2 == null) {
return true;
}
if (item1 == null || item2 == null) {
return true;
}
if (!item1.getType().equals(item2.getType())) {
return false;
}
if(item1.isSimilar(item2)) {
return true;
}
if (item1.hasItemMeta() && item2.hasItemMeta()) {
return metaMatches(item1, item2);
}
return !item1.hasItemMeta() && !item1.hasItemMeta();
}
protected static boolean metaMatches(ItemStack item1, ItemStack item2) {
ItemMeta meta1 = item1.getItemMeta();
ItemMeta meta2 = item2.getItemMeta();
if (meta1 != null && meta2 != null) {
for (Matcher matcher : matcherList) {
boolean result = matcher.match(meta1, meta2);
if (!result) {
return false;
}
}
return true;
}
return meta1 == null && meta2 == null;
}
private static boolean listMatches(Collection<?> list1, Collection<?> list2) {
return list1.containsAll(list2) && list2.containsAll(list1);
}
public static interface Matcher {
boolean match(ItemMeta meta1, ItemMeta meta2);
}
}