AcesDephtPest 发表于 2024-8-28 21:27:26

ItemStack(映射版,但是是NBT丢失)

本帖最后由 AcesDephtPest 于 2024-8-30 20:16 编辑

NBT丢失,没啥好说的,有大佬解释下吗awa
public static class ItemStack implements Serializable {
      @Serial
      private static final long serialVersionUID = 1L;

      public static class metas {
            private static Class<?> PotionTypeClass;

            private static final Class<?> ArmorMetaClass = loadClass("ArmorMeta");
            private static final Class<?> AxolotlBucketMetaClass = loadClass("AxolotlBucketMeta");
            private static final Class<?> BannerMetaClass = loadClass("BannerMeta");
            private static final Class<?> BlockDataMetaClass = loadClass("BlockData");
            private static final Class<?> BlockStateMetaClass = loadClass("BlockState");
            private static final Class<?> BookMetaClass = loadClass("BookMeta");
            private static final Class<?> BookMetaGenerationClass = loadClass("BookMeta.Generation"); // 假设有 Generation 枚举
            private static final Class<?> BundleMetaClass = loadClass("BundleMeta");
            private static final Class<?> ColorableArmorMetaClass = loadClass("LeatherArmorMeta"); // 注意: 皮革盔甲是可以染色的
            private static final Class<?> CompassMetaClass = loadClass("CompassMeta");
            private static final Class<?> CrossbowMetaClass = loadClass("CrossbowMeta");
            private static final Class<?> DamageableClass = loadClass("Damageable");
            private static final Class<?> EnchantmentStorageMetaClass = loadClass("EnchantmentStorageMeta");
            private static final Class<?> FireworkEffectMetaClass = loadClass("FireworkEffectMeta");
            private static final Class<?> FireworkMetaClass = loadClass("FireworkMeta");
            private static final Class<?> KnowledgeBookMetaClass = loadClass("KnowledgeBookMeta");
            private static final Class<?> LeatherArmorMetaClass = loadClass("LeatherArmorMeta");
            private static final Class<?> MapMetaClass = loadClass("MapMeta");
            private static final Class<?> MusicInstrumentMetaClass = loadClass("MusicInstrumentMeta");
            private static final Class<?> OminousBottleMetaClass = loadClass("OminousBottleMeta");
            private static final Class<?> PotionMetaClass = loadClass("PotionMeta");
            private static final Class<?> RepairableClass = loadClass("Repairable");
            private static final Class<?> SkullMetaClass = loadClass("SkullMeta");
            private static final Class<?> SpawnEggMetaClass = loadClass("SpawnEggMeta");
            private static final Class<?> SuspiciousStewMetaClass = loadClass("SuspiciousStewMeta");
            private static final Class<?> TropicalFishBucketMetaClass = loadClass("TropicalFishBucketMeta");
            private static final Class<?> WritableBookMetaClass = loadClass("WritableBookMeta");
            // 动态加载类的私有方法
            private static Class<?> loadClass(String className) {
                try {
                  return Class.forName("org.bukkit.inventory.meta." + className);
                } catch (ClassNotFoundException e) {
                  System.err.println("Class org.bukkit.inventory.meta." + className + " not found.");
                  return null;
                }
            }
      }
      private Material type = Material.AIR;
      private int amount = 0;
      private List<String> lore = new ArrayList<>();
      private String displayName = null;
      private Map<String, Integer> enchantments = new HashMap<>(); // 存储附魔名称和级别
      private Object potionType = null; // 药水类型
      private boolean isSplash = false; // 是否为喷溅药水
      private String Variant = null; // 代表一桶蝾螈
      private List<Object> BannerMeta = null; // 旗帜的图案的列表
      private Location CompassMeta = null; // 代表能追踪指定位置的指南针
      private short Damageable = 0; // 代表有耐久度,可损耗的物品
      private Map<String, Integer> EnchantmentStorageMeta = new HashMap<>(); // 特定于专门存储附魔的物品,而非被附魔的物品. 附魔书 就是一个可存储附魔的物品的例子.
      private Object FireworkEffectMeta = null; // 烟花效果
      private List<Object> FireworkMeta = new ArrayList<>(); // 烟花火箭及其效果
      private List<Object> KnowledgeBookMeta = new ArrayList<>(); //与知识之书有关的元数据
      private Color LeatherArmorMeta = null; // 下文中的"盔甲"可以是皮革靴子,外套,帽子,裤子任意一种,因为这个类代表了四种嘛
      private Color MapMetaColor = null; // 伸缩的地图
      private Object MapMetaMapView = null; // 伸缩的地图
      private int Repairable = 0; //修复此物品所需的额外经验等级
      private Object SkullMetaOfflinePlayer = null; //头颅的主人
      private List<Object> SuspiciousStewMeta = new ArrayList<>(); //自定义药水效果的迷之炖菜
      private Object TropicalFishBucketMetaBodyColor = null; //热带鱼桶
      private Object TropicalFishBucketMetaPattern = null; //热带鱼桶
      private Object TropicalFishBucketMetaPatternColor = null; // 热带鱼桶
      private String BookMetaAuthor = null; // 热带鱼桶
      private Object BookMetaGeneration = null; // 热带鱼桶
      private List<String> BookMetaPages = null; // 热带鱼桶
      private String BookMetaTitle = null;
      public ItemStack(org.bukkit.inventory.ItemStack itemStack) {
            if (itemStack != null && itemStack.getType() != Material.AIR) {
                this.type = itemStack.getType();
                this.amount = itemStack.getAmount();
                getMeta(itemStack.getItemMeta());
                this.enchantments = new HashMap<>();
                for (Map.Entry<Enchantment, Integer> entry : itemStack.getEnchantments().entrySet()) {
                  this.enchantments.put(entry.getKey().getKey().toString(), entry.getValue());
                }
            }
      }
      public org.bukkit.inventory.ItemStack toItemStack() {
            org.bukkit.inventory.ItemStack itemStack = new org.bukkit.inventory.ItemStack(this.type, this.amount);
            itemStack.setItemMeta(setMeta(itemStack.getItemMeta()));
            return itemStack;
      }
      public Object classTo(Class<?> clazz, String name,ItemMeta meta) {
            if (clazz != null && clazz.isInstance(meta)) {
                try {
                  Method method = clazz.getMethod(name);
                  return method.invoke(meta);
                } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException ignored) {}
            }
            return null;
      }

      public void classSet(Class<?> clazz, String name, Object object, ItemMeta meta) {
            if (clazz != null && clazz.isInstance(meta)) {
                try {
                  Method setDamageMethod = clazz.getMethod(name, object.getClass());
                  setDamageMethod.invoke(meta, object);
                } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException ignored) {}
            }
      }
      @SuppressWarnings("unchecked")
      public void getMeta(ItemMeta meta) {
            if (meta != null) {
                if (metas.DamageableClass != null && metas.DamageableClass.isInstance(meta)) {
                  Integer integerValue = (Integer) classTo(metas.DamageableClass, "getDamage", meta);
                  if (integerValue != null && integerValue >= Short.MIN_VALUE && integerValue <= Short.MAX_VALUE) this.Damageable = integerValue.shortValue();
                  else System.out.println(integerValue);
                }
                if (metas.TropicalFishBucketMetaClass != null && metas.TropicalFishBucketMetaClass.isInstance(meta)) this.Variant = (String) classTo(metas.AxolotlBucketMetaClass,"getVariant",meta);
                if (metas.BannerMetaClass != null && metas.BannerMetaClass.isInstance(meta)) this.BannerMeta = (List<Object>) classTo(metas.BannerMetaClass,"getPatterns",meta);
                if (metas.CompassMetaClass != null && metas.CompassMetaClass.isInstance(meta)) this.CompassMeta = (Location) classTo(metas.CompassMetaClass,"getLodestone",meta);
                if (metas.EnchantmentStorageMetaClass != null && metas.EnchantmentStorageMetaClass.isInstance(meta)) {
                  this.EnchantmentStorageMeta = new HashMap<>();
                  Map<Enchantment, Integer> list = (Map<Enchantment, Integer>) classTo(metas.EnchantmentStorageMetaClass, "getStoredEnchants", meta);
                  for (Map.Entry<Enchantment, Integer> entry : list.entrySet()) {
                        this.EnchantmentStorageMeta.put(entry.getKey().getKey().toString(), entry.getValue());
                  }
                }
                if (metas.FireworkEffectMetaClass != null && metas.FireworkEffectMetaClass.isInstance(meta)) this.FireworkEffectMeta = (FireworkEffect) classTo(metas.FireworkEffectMetaClass,"getEffect",meta);
                if (metas.FireworkMetaClass != null && metas.FireworkMetaClass.isInstance(meta)) this.FireworkMeta = (List<Object>) classTo(metas.FireworkMetaClass,"getEffects",meta);
                if (metas.KnowledgeBookMetaClass != null && metas.KnowledgeBookMetaClass.isInstance(meta)) this.KnowledgeBookMeta = (List<Object>) classTo(metas.KnowledgeBookMetaClass,"getRecipes",meta);
                if (metas.LeatherArmorMetaClass != null && metas.LeatherArmorMetaClass.isInstance(meta)) this.LeatherArmorMeta = (Color) classTo(metas.LeatherArmorMetaClass,"getColor",meta);

                if (metas.MapMetaClass != null && metas.MapMetaClass.isInstance(meta)) {
                  this.MapMetaColor = (Color) classTo(metas.MapMetaClass, "getColor", meta);
                  this.MapMetaMapView = (MapView) classTo(metas.MapMetaClass, "getColor", meta);
                }
                if (metas.RepairableClass != null && metas.RepairableClass.isInstance(meta)) this.Repairable = (int) classTo(metas.RepairableClass, "getRepairCost", meta);
                if (metas.SkullMetaClass != null && metas.SkullMetaClass.isInstance(meta)) this.SkullMetaOfflinePlayer = classTo(metas.SkullMetaClass,"getOwningPlayer",meta);
                if (metas.SuspiciousStewMetaClass != null && metas.SuspiciousStewMetaClass.isInstance(meta)) this.SuspiciousStewMeta = (List<Object>) classTo(metas.SuspiciousStewMetaClass,"getCustomEffects",meta);
                if (metas.TropicalFishBucketMetaClass != null && metas.TropicalFishBucketMetaClass.isInstance(meta)) {
                  this.TropicalFishBucketMetaPattern = classTo(metas.TropicalFishBucketMetaClass,"getPattern",meta);
                  this.TropicalFishBucketMetaBodyColor = classTo(metas.TropicalFishBucketMetaClass,"getBodyColor",meta);
                  this.TropicalFishBucketMetaPatternColor = classTo(metas.TropicalFishBucketMetaClass,"getPatternColor",meta);
                }
                if (metas.BookMetaClass != null && metas.BookMetaClass.isInstance(meta)) {
                  this.BookMetaAuthor = (String) classTo(metas.BookMetaClass, "getAuthor", meta);
                  this.BookMetaGeneration = classTo(metas.BookMetaClass, "getGeneration", meta);
                  this.BookMetaPages = (List<String>) classTo(metas.BookMetaClass, "getPages", meta);
                  this.BookMetaTitle = (String) classTo(metas.BookMetaClass, "getTitle", meta);
                }
                this.lore = Objects.requireNonNull(meta).hasLore() ? new ArrayList<>(Objects.requireNonNull(meta.getLore())) : null;
                this.displayName = meta.hasDisplayName() ? meta.getDisplayName() : null;
                if ((metas.PotionMetaClass != null && metas.PotionMetaClass.isInstance(meta)) &&
                        this.type.equals(Material.POTION) || this.type.equals(Material.SPLASH_POTION) || this.type.equals(Material.LINGERING_POTION)) {
                  try {
                        this.potionType = classTo(metas.PotionMetaClass, "getBasePotionData", meta).getClass().getMethod("getType").invoke(meta);
                  } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException ignored) {}
                  this.isSplash = this.type == Material.SPLASH_POTION;
                }
            }
      }
      public ItemMeta setMeta(ItemMeta meta) {
            if (meta != null) {
                if (this.displayName != null) meta.setDisplayName(this.displayName);
                if (this.lore != null) meta.setLore(this.lore);
                if (this.enchantments != null && !this.enchantments.isEmpty()) for (Map.Entry<String, Integer> entry : this.enchantments.entrySet()) {
                  Enchantment enchantment = Enchantment.getByKey(NamespacedKey.fromString(entry.getKey()));
                  if (enchantment != null) meta.addEnchant(enchantment, entry.getValue(), true);
                }



                if (instance(meta,metas.DamageableClass)) classSet(metas.DamageableClass,"setDamage",this.Damageable,meta);
                if (instance(meta,metas.TropicalFishBucketMetaClass)) classSet(metas.AxolotlBucketMetaClass,"setVariant",this.Variant,meta);
                if (instance(meta,metas.BannerMetaClass)) classSet(metas.BannerMetaClass,"setPatterns",this.BannerMeta,meta);
                if (instance(meta,metas.CompassMetaClass)) classSet(metas.CompassMetaClass,"setLodestone",this.CompassMeta,meta);
                if (instance(meta,metas.EnchantmentStorageMetaClass) && this.EnchantmentStorageMeta != null && !this.EnchantmentStorageMeta.isEmpty()) for (Map.Entry<String, Integer> entry : this.EnchantmentStorageMeta.entrySet()) {
                  Enchantment enchantment = Enchantment.getByKey(NamespacedKey.fromString(entry.getKey()));
                  if (enchantment != null && metas.EnchantmentStorageMetaClass.isInstance(meta)) {
                        try {
                            Method setDamageMethod = metas.EnchantmentStorageMetaClass.getMethod("addStoredEnchant", Enchantment.class,Integer.class,Boolean.class);
                            setDamageMethod.invoke(meta, enchantment, entry.getValue(), true);
                        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException ignored) {}
                  }
                }
                if (instance(meta,metas.FireworkEffectMetaClass)) classSet(metas.FireworkEffectMetaClass,"setEffect",this.FireworkEffectMeta,meta);
                if (instance(meta,metas.FireworkMetaClass)) classSet(metas.FireworkMetaClass,"setEffects",this.FireworkMeta,meta);
                if (instance(meta,metas.KnowledgeBookMetaClass)) classSet(metas.KnowledgeBookMetaClass,"setRecipes",this.KnowledgeBookMeta,meta);
                if (instance(meta,metas.LeatherArmorMetaClass)) classSet(metas.LeatherArmorMetaClass,"setColor",this.LeatherArmorMeta,meta);
                if (instance(meta,metas.MapMetaClass)) {
                  classSet(metas.MapMetaClass, "setColor",this.MapMetaColor, meta);
                  classSet(metas.MapMetaClass, "setColor",this.MapMetaMapView, meta);
                }
                if (instance(meta,metas.RepairableClass)) classSet(metas.RepairableClass, "setRepairCost",this.Repairable, meta);
                if (instance(meta,metas.SkullMetaClass)) classSet(metas.SkullMetaClass,"setOwningPlayer",this.SkullMetaOfflinePlayer,meta);
                if (instance(meta,metas.SuspiciousStewMetaClass)) classSet(metas.SuspiciousStewMetaClass,"setCustomEffects",this.SuspiciousStewMeta,meta);
                if (instance(meta,metas.TropicalFishBucketMetaClass)) {
                  classSet(metas.TropicalFishBucketMetaClass,"setPattern",this.TropicalFishBucketMetaPattern,meta);
                  classSet(metas.TropicalFishBucketMetaClass,"setBodyColor",this.TropicalFishBucketMetaBodyColor,meta);
                  classSet(metas.TropicalFishBucketMetaClass,"setPatternColor",this.TropicalFishBucketMetaPatternColor,meta);
                }
                if (instance(meta,metas.BookMetaClass)) {
                  classSet(metas.BookMetaClass, "setAuthor",this.BookMetaAuthor, meta);
                  classSet(metas.BookMetaClass, "setGeneration",this.BookMetaGeneration, meta);
                  classSet(metas.BookMetaClass, "setPages",this.BookMetaPages, meta);
                  classSet(metas.BookMetaClass, "setTitle",this.BookMetaTitle, meta);
                }
                this.lore = Objects.requireNonNull(meta).hasLore() ? new ArrayList<>(Objects.requireNonNull(meta.getLore())) : null;
                this.displayName = meta.hasDisplayName() ? meta.getDisplayName() : null;
                if (instance(meta,metas.PotionMetaClass) && this.type.equals(Material.POTION) || this.type.equals(Material.SPLASH_POTION) || this.type.equals(Material.LINGERING_POTION)) {
                  try {
                        this.potionType = classTo(metas.PotionMetaClass, "getBasePotionData", meta).getClass().getMethod("getType").invoke(meta);
                  } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException ignored) {}
                  this.isSplash = this.type == Material.SPLASH_POTION;
                }
                if (instance(meta,metas.DamageableClass) && this.Damageable > 0) classSet(metas.DamageableClass,"setDamage",this.Damageable,meta);
                if (instance(meta,metas.PotionMetaClass) && this.potionType != null) {
                  if (this.type.equals(Material.POTION) || this.type.equals(Material.LINGERING_POTION) || this.type.equals(Material.SPLASH_POTION)) {
                        if (metas.PotionMetaClass.isInstance(meta)) {
                            try {
                              Constructor<?> potionDataConstructor = metas.PotionTypeClass.getConstructor(boolean.class, boolean.class, boolean.class);
                              Method setBasePotionDataMethod = metas.PotionMetaClass.getMethod("setBasePotionData", metas.PotionTypeClass);
                              setBasePotionDataMethod.invoke(meta, potionDataConstructor.newInstance(
                                        !isSplash && (boolean) classTo(this.potionType.getClass(),"isExtendable",meta),
                                        isSplash && (boolean) classTo(this.potionType.getClass(),"isUpgradeable",meta),
                                        false
                              ));
                            } catch (Exception ignored) {}
                        }
                  }
                }
                if (instance(meta,metas.AxolotlBucketMetaClass) && this.Variant != null) {
                  classSet(metas.AxolotlBucketMetaClass,"setVariant",this.Variant,meta);
                }
                if (instance(meta,metas.BannerMetaClass) && this.BannerMeta != null) {
                  classSet(metas.BannerMetaClass,"setPatterns",this.BannerMeta,meta);
                }
                if (instance(meta,metas.CompassMetaClass) && this.CompassMeta != null) {
                  classSet(metas.CompassMetaClass,"setLodestone",this.CompassMeta.toLocation(),meta);
                }
                if (instance(meta,metas.FireworkEffectMetaClass) && this.FireworkEffectMeta != null) {
                  classSet(metas.FireworkEffectMetaClass,"setEffect",this.FireworkEffectMeta,meta);
                }
                if (instance(meta,metas.FireworkMetaClass) && this.FireworkMeta != null) {
                  classSet(metas.FireworkMetaClass,"addEffects",this.FireworkMeta,meta);
                }
                if (instance(meta,metas.KnowledgeBookMetaClass) && this.KnowledgeBookMeta != null) {
                  classSet(metas.KnowledgeBookMetaClass,"setRecipes",this.KnowledgeBookMeta,meta);
                }
                if (instance(meta,metas.LeatherArmorMetaClass) && this.LeatherArmorMeta != null) {
                  classSet(metas.LeatherArmorMetaClass,"setColor",this.LeatherArmorMeta,meta);
                }
                if (instance(meta,metas.MapMetaClass)) {

                  if (this.MapMetaColor != null) classSet(metas.MapMetaClass,"setColor",this.MapMetaColor,meta);
                  if (this.MapMetaMapView != null) classSet(metas.MapMetaClass,"setMapView",this.MapMetaMapView,meta);
                }
                if (instance(meta,metas.RepairableClass) && this.Repairable > 0) {
                  classSet(metas.RepairableClass,"setRepairCost",this.Repairable,meta);
                }
                if (instance(meta,metas.SkullMetaClass) && this.SkullMetaOfflinePlayer != null) {
                  classSet(metas.SkullMetaClass,"setOwningPlayer",this.SkullMetaOfflinePlayer,meta);
                }
                if (instance(meta,metas.SuspiciousStewMetaClass) && this.SuspiciousStewMeta != null) {
                  for (Object data : this.SuspiciousStewMeta)
                        if (data != null && metas.SuspiciousStewMetaClass.isInstance(meta)) {
                        try {
                            Method setDamageMethod = metas.SuspiciousStewMetaClass.getMethod("addCustomEffect", Object.class,Boolean.class);
                            setDamageMethod.invoke(meta, data, true);
                        } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException ignored) {}
                  }
                }
                if (instance(meta,metas.TropicalFishBucketMetaClass)) {
                  if (this.TropicalFishBucketMetaBodyColor != null) classSet(metas.TropicalFishBucketMetaClass,"setBodyColor",this.TropicalFishBucketMetaBodyColor,meta);
                  if (this.TropicalFishBucketMetaPattern != null) classSet(metas.TropicalFishBucketMetaClass,"setPattern",this.TropicalFishBucketMetaPattern,meta);
                  if (this.TropicalFishBucketMetaPatternColor != null) classSet(metas.TropicalFishBucketMetaClass,"setPatternColor",this.TropicalFishBucketMetaPatternColor,meta);
                }
                if (instance(meta,metas.BookMetaClass)) {
                  if (this.BookMetaAuthor != null) classSet(metas.BookMetaClass,"setAuthor",this.BookMetaAuthor,meta);
                  if (this.BookMetaGeneration != null) classSet(metas.BookMetaClass,"setGeneration",this.BookMetaGeneration,meta);
                  if (this.BookMetaPages != null) classSet(metas.BookMetaClass,"setPages",this.BookMetaPages,meta);
                  if (this.BookMetaTitle != null) classSet(metas.BookMetaClass,"setTitle",this.BookMetaTitle,meta);
                }
            }
            return meta;
      }
      public static boolean instance(ItemMeta meta,Class<?> clazz) {
            return clazz != null && clazz.isInstance(meta);
      }
      public static class Location implements Serializable {
            private final double x;
            private final double y;
            private final double z;
            private final World world;
            public Location(org.bukkit.Location location) {
                this.world = location.getWorld();
                this.x = location.getX();
                this.y = location.getY();
                this.z = location.getZ();
            }
            public org.bukkit.Location toLocation() {
                return new org.bukkit.Location(this.world,this.x,this.y,this.z);
            }
      }
    }



public static class ItemStack implements Serializable {
    @Serial
    private static final long serialVersionUID = 1L;

    public static class metas {
      private static final Class<?> PotionTypeClass = toClass("org.bukkit.potion.PotionType");

      private static final Class<?> ArmorMetaClass = loadClass("ArmorMeta");
      private static final Class<?> AxolotlBucketMetaClass = loadClass("AxolotlBucketMeta");
      private static final Class<?> BannerMetaClass = loadClass("BannerMeta");
      private static final Class<?> BlockDataMetaClass = loadClass("BlockData");
      private static final Class<?> BlockStateMetaClass = loadClass("BlockState");
      private static final Class<?> BookMetaClass = loadClass("BookMeta");
      private static final Class<?> BookMetaGenerationClass = loadClass("BookMeta.Generation"); // 假设有 Generation 枚举
      private static final Class<?> BundleMetaClass = loadClass("BundleMeta");
      private static final Class<?> ColorableArmorMetaClass = loadClass("LeatherArmorMeta"); // 注意: 皮革盔甲是可以染色的
      private static final Class<?> CompassMetaClass = loadClass("CompassMeta");
      private static final Class<?> CrossbowMetaClass = loadClass("CrossbowMeta");
      private static final Class<?> DamageableClass = loadClass("Damageable");
      private static final Class<?> EnchantmentStorageMetaClass = loadClass("EnchantmentStorageMeta");
      private static final Class<?> FireworkEffectMetaClass = loadClass("FireworkEffectMeta");
      private static final Class<?> FireworkMetaClass = loadClass("FireworkMeta");
      private static final Class<?> KnowledgeBookMetaClass = loadClass("KnowledgeBookMeta");
      private static final Class<?> LeatherArmorMetaClass = loadClass("LeatherArmorMeta");
      private static final Class<?> MapMetaClass = loadClass("MapMeta");
      private static final Class<?> MusicInstrumentMetaClass = loadClass("MusicInstrumentMeta");
      private static final Class<?> OminousBottleMetaClass = loadClass("OminousBottleMeta");
      private static final Class<?> PotionMetaClass = loadClass("PotionMeta");
      private static final Class<?> PotionEffectType = toClass("org.bukkit.potion.PotionEffectType");
      private static final Class<?> RepairableClass = loadClass("Repairable");
      private static final Class<?> SkullMetaClass = loadClass("SkullMeta");
      private static final Class<?> SpawnEggMetaClass = loadClass("SpawnEggMeta");
      private static final Class<?> SuspiciousStewMetaClass = loadClass("SuspiciousStewMeta");
      private static final Class<?> TropicalFishBucketMetaClass = loadClass("TropicalFishBucketMeta");
      private static final Class<?> WritableBookMetaClass = loadClass("WritableBookMeta");
      // 动态加载类的私有方法
      private static Class<?> loadClass(String className) {
            try {
                return Class.forName("org.bukkit.inventory.meta." + className);
            } catch (ClassNotFoundException e) {
                System.err.println("Class org.bukkit.inventory.meta." + className + " not found.");
                return null;
            }
      }
      private static Class<?> toClass(String className) {
            try {
                return Class.forName(className);
            } catch (ClassNotFoundException e) {
                System.err.println("Class " + className + " not found.");
                return null;
            }
      }
    }
    private Material type = Material.AIR;
    private int amount = 0;
    private List<String> lore = new ArrayList<>();
    private String displayName = null;
    private Map<String, Integer> enchantments = new HashMap<>(); // 存储附魔名称和级别

    private String PotionEffectType = null; // 药水类型
    private boolean PotionIsUpgradeable;
    private boolean PotionIsExtendable;

    private boolean isSplash = false; // 是否为喷溅药水
    private String Variant = null; // 代表一桶蝾螈
    private List<Map<String, Object>> BannerMeta = null; // 旗帜的图案的列表
    private Location CompassMeta = null; // 代表能追踪指定位置的指南针
    private int Damageable = 0; // 代表有耐久度,可损耗的物品
    private Map<String, Integer> EnchantmentStorageMeta = new HashMap<>(); // 特定于专门存储附魔的物品,而非被附魔的物品. 附魔书 就是一个可存储附魔的物品的例子.
    private Object FireworkEffectMeta = null; // 烟花效果
    private List<Object> FireworkMeta = new ArrayList<>(); // 烟花火箭及其效果
    private List<Object> KnowledgeBookMeta = new ArrayList<>(); //与知识之书有关的元数据
    private Color LeatherArmorMeta = null; // 下文中的"盔甲"可以是皮革靴子,外套,帽子,裤子任意一种,因为这个类代表了四种嘛
    private Color MapMetaColor = null; // 伸缩的地图
    private Object MapMetaMapView = null; // 伸缩的地图
    private int Repairable = 0; //修复此物品所需的额外经验等级
    private Object SkullMetaOfflinePlayer = null; //头颅的主人
    private List<Object> SuspiciousStewMeta = new ArrayList<>(); //自定义药水效果的迷之炖菜
    private Object TropicalFishBucketMetaBodyColor = null; //热带鱼桶
    private Object TropicalFishBucketMetaPattern = null; //热带鱼桶
    private Object TropicalFishBucketMetaPatternColor = null; // 热带鱼桶
    private String BookMetaAuthor = null; // 热带鱼桶
    private Object BookMetaGeneration = null; // 热带鱼桶
    private List<String> BookMetaPages = null; // 热带鱼桶
    private String BookMetaTitle = null;
    public ItemStack(org.bukkit.inventory.ItemStack itemStack) {
      if (itemStack != null && itemStack.getType() != Material.AIR) {
            this.type = itemStack.getType();
            this.amount = itemStack.getAmount();
            getMeta(itemStack.getItemMeta());
            this.enchantments = new HashMap<>();
            for (Map.Entry<Enchantment, Integer> entry : itemStack.getEnchantments().entrySet()) {
                this.enchantments.put(entry.getKey().getKey().toString(), entry.getValue());
            }
      }
    }
    public org.bukkit.inventory.ItemStack toItemStack() {
      org.bukkit.inventory.ItemStack itemStack = new org.bukkit.inventory.ItemStack(this.type, this.amount);
      try {
            itemStack.setItemMeta(setMeta(itemStack.getItemMeta()));
      } catch (Exception e) {
            e.printStackTrace();
      }

      return itemStack;
    }
    public static Object classTo(Class<?> clazz, String name, ItemMeta obj) {
      if (clazz!= null && clazz.isInstance(obj)) {
            try {
                Method method = clazz.getMethod(name);
                Object result = method.invoke(obj);
                if (result instanceof Number) {
                  return ((Number) result).intValue();
                } else if (result instanceof String) {
                  return result.toString();
                } else {
                  return result;
                }
            } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
                e.printStackTrace();
            }
      }
      return null;
    }
    public static <T> void classSet(Class<?> clazz, String methodName, T object, ItemMeta meta) {
      if (clazz != null && clazz.isInstance(meta)) {
            Method method;
            try {
                Class<?> paramType = object == null ? null : object.getClass();
                if (paramType == Integer.class) {
                  try {
                        method = clazz.getMethod(methodName, int.class);
                  } catch (NoSuchMethodException e) {
                        method = clazz.getMethod(methodName, Integer.class);
                  }
                } else if (paramType == ArrayList.class) {
                  try {
                        method = clazz.getMethod(methodName, List.class);
                  } catch (NoSuchMethodException e) {
                        method = clazz.getMethod(methodName, ArrayList.class);
                  }
                } else {
                  method = clazz.getMethod(methodName, paramType);
                }
                method.invoke(meta, object);
            } catch (NoSuchMethodException e) {
                // 方法不存在
                System.out.println("No such method " + methodName + " found for class " + clazz.getName());
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                // 方法无法访问
                System.out.println("Cannot access method " + methodName + " for class " + clazz.getName());
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                // 被调用方法发生异常
                System.out.println("Method " + methodName + " threw an exception for class " + clazz.getName());
                e.printStackTrace();
            }
      }
    }
    @SuppressWarnings("unchecked")
    public void getMeta(ItemMeta meta) {
      if (meta != null) {
            if (metas.DamageableClass != null && metas.DamageableClass.isInstance(meta)) {
                this.Damageable = (Integer) classTo(metas.DamageableClass, "getDamage", meta);
            }
            if (metas.TropicalFishBucketMetaClass != null && metas.TropicalFishBucketMetaClass.isInstance(meta)) this.Variant = (String) classTo(metas.AxolotlBucketMetaClass,"getVariant",meta);
            if (metas.BannerMetaClass != null && metas.BannerMetaClass.isInstance(meta)) {
                int count = (int) classTo(metas.BannerMetaClass,"numberOfPatterns",meta);
                BannerMeta = new ArrayList<>(count);
                for (int i = 0; i < count; i++) {
                  try {
                        Object patternObject = metas.BannerMetaClass.getMethod("getPattern", int.class).invoke(meta, i);
                        Method serializeMethod = patternObject.getClass().getMethod("serialize");
                        Object serializedResult = serializeMethod.invoke(patternObject);
                        BannerMeta.add((Map<String, Object>) serializedResult);
                  } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException ignored) {}
                }
            }
            if (metas.CompassMetaClass != null && metas.CompassMetaClass.isInstance(meta)) this.CompassMeta = (Location) classTo(metas.CompassMetaClass,"getLodestone",meta);
            if (metas.EnchantmentStorageMetaClass != null && metas.EnchantmentStorageMetaClass.isInstance(meta)) {
                this.EnchantmentStorageMeta = new HashMap<>();
                //((org.bukkit.inventory.meta.EnchantmentStorageMeta) meta).getStoredEnchants()
                Map<Enchantment, Integer> list = (Map<Enchantment, Integer>) classTo(metas.EnchantmentStorageMetaClass, "getStoredEnchants", meta);
                for (Map.Entry<Enchantment, Integer> entry : list.entrySet()) {
                  this.EnchantmentStorageMeta.put(entry.getKey().getKey().toString(), entry.getValue());
                }
            }
            if (metas.FireworkEffectMetaClass != null && metas.FireworkEffectMetaClass.isInstance(meta)) this.FireworkEffectMeta = (FireworkEffect) classTo(metas.FireworkEffectMetaClass,"getEffect",meta);
            if (metas.FireworkMetaClass != null && metas.FireworkMetaClass.isInstance(meta)) this.FireworkMeta = (List<Object>) classTo(metas.FireworkMetaClass,"getEffects",meta);
            if (metas.KnowledgeBookMetaClass != null && metas.KnowledgeBookMetaClass.isInstance(meta)) this.KnowledgeBookMeta = (List<Object>) classTo(metas.KnowledgeBookMetaClass,"getRecipes",meta);
            if (metas.LeatherArmorMetaClass != null && metas.LeatherArmorMetaClass.isInstance(meta)) this.LeatherArmorMeta = (Color) classTo(metas.LeatherArmorMetaClass,"getColor",meta);

            if (metas.MapMetaClass != null && metas.MapMetaClass.isInstance(meta)) {
                this.MapMetaColor = (Color) classTo(metas.MapMetaClass, "getColor", meta);
                this.MapMetaMapView = classTo(metas.MapMetaClass, "getColor", meta);
            }
            if (metas.RepairableClass != null && metas.RepairableClass.isInstance(meta)) this.Repairable = (int) classTo(metas.RepairableClass, "getRepairCost", meta);
            if (metas.SkullMetaClass != null && metas.SkullMetaClass.isInstance(meta)) this.SkullMetaOfflinePlayer = classTo(metas.SkullMetaClass,"getOwningPlayer",meta);
            if (metas.SuspiciousStewMetaClass != null && metas.SuspiciousStewMetaClass.isInstance(meta)) this.SuspiciousStewMeta = (List<Object>) classTo(metas.SuspiciousStewMetaClass,"getCustomEffects",meta);
            if (metas.TropicalFishBucketMetaClass != null && metas.TropicalFishBucketMetaClass.isInstance(meta)) {
                this.TropicalFishBucketMetaPattern = classTo(metas.TropicalFishBucketMetaClass,"getPattern",meta);
                this.TropicalFishBucketMetaBodyColor = classTo(metas.TropicalFishBucketMetaClass,"getBodyColor",meta);
                this.TropicalFishBucketMetaPatternColor = classTo(metas.TropicalFishBucketMetaClass,"getPatternColor",meta);
            }
            if (metas.BookMetaClass != null && metas.BookMetaClass.isInstance(meta)) {
                this.BookMetaAuthor = (String) classTo(metas.BookMetaClass, "getAuthor", meta);
                this.BookMetaGeneration = classTo(metas.BookMetaClass, "getGeneration", meta);
                this.BookMetaPages = (List<String>) classTo(metas.BookMetaClass, "getPages", meta);
                this.BookMetaTitle = (String) classTo(metas.BookMetaClass, "getTitle", meta);
            }
            this.lore = Objects.requireNonNull(meta).hasLore() ? new ArrayList<>(Objects.requireNonNull(meta.getLore())) : null;
            this.displayName = meta.hasDisplayName() ? meta.getDisplayName() : null;
            if ((metas.PotionMetaClass != null && metas.PotionMetaClass.isInstance(meta)) &&
                  (this.type.equals(Material.POTION) || this.type.equals(Material.SPLASH_POTION) || this.type.equals(Material.LINGERING_POTION))) {
                try {
                  //((PotionMeta) meta).getBasePotionData().getType().isUpgradeable()
                  Object getBasePotionData = metas.PotionMetaClass.getMethod("getBasePotionData").invoke(meta);
                  if (getBasePotionData != null) {
                        Object getType = getBasePotionData.getClass().getMethod("getType").invoke(getBasePotionData);
                        Object getEffectType = getType.getClass().getMethod("getEffectType").invoke(getType);
                        this.PotionEffectType = (String) getEffectType.getClass().getMethod("getName").invoke(getEffectType);
                        this.PotionIsExtendable = (boolean) getType.getClass().getMethod("isExtendable").invoke(getType);
                        this.PotionIsUpgradeable = (boolean) getType.getClass().getMethod("isUpgradeable").invoke(getType);
                        this.isSplash = this.type == Material.SPLASH_POTION;
                  }
                } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
                  e.printStackTrace();
                }
            }
      }
    }
    public ItemMeta setMeta(ItemMeta meta) {
      if (meta != null) {
            if (this.displayName != null) meta.setDisplayName(this.displayName);
            if (this.lore != null) meta.setLore(this.lore);
            if (this.enchantments != null && !this.enchantments.isEmpty()) for (Map.Entry<String, Integer> entry : this.enchantments.entrySet()) {
                Enchantment enchantment = Enchantment.getByKey(NamespacedKey.fromString(entry.getKey()));
                if (enchantment != null) meta.addEnchant(enchantment, entry.getValue(), true);
            }
            if (instance(meta,metas.DamageableClass)) classSet(metas.DamageableClass,"setDamage",this.Damageable,meta);
            if (instance(meta,metas.TropicalFishBucketMetaClass)) classSet(metas.AxolotlBucketMetaClass,"setVariant",this.Variant,meta);
            //((org.bukkit.inventory.meta.BannerMeta) meta).setPattern();
            if (instance(meta, metas.BannerMetaClass) && this.BannerMeta != null) {
                try {
                  List<Map<String, Object>> patternDataList = new ArrayList<>(this.BannerMeta);
                  Method setPatternMethod = metas.BannerMetaClass.getMethod("setPatterns", List.class);
                  setPatternMethod.invoke(meta, patternDataList.stream()
                            .map(patternData -> {
                              try {
                                    // 使用构造函数创建 Pattern 实例
                                    return Class.forName("org.bukkit.block.banner.Pattern")
                                          .getConstructor(Map.class).newInstance(patternData);
                              } catch (InstantiationException | IllegalAccessException |
                                       InvocationTargetException | ClassNotFoundException |
                                       NoSuchMethodException e) {
                                    e.printStackTrace();
                                    return null;
                              }
                            })
                            .filter(Objects::nonNull) // 过滤掉任何 null 值
                            .collect(Collectors.toList()));
                } catch (NoSuchMethodException | IllegalAccessException |
                         InvocationTargetException e) {
                  e.printStackTrace();
                }
            }
            if (instance(meta,metas.CompassMetaClass)) classSet(metas.CompassMetaClass,"setLodestone",this.CompassMeta,meta);
            if (instance(meta,metas.EnchantmentStorageMetaClass) && this.EnchantmentStorageMeta != null && !this.EnchantmentStorageMeta.isEmpty()) for (Map.Entry<String, Integer> entry : this.EnchantmentStorageMeta.entrySet()) {
                Enchantment enchantment = Enchantment.getByKey(NamespacedKey.fromString(entry.getKey()));
                if (enchantment != null && metas.EnchantmentStorageMetaClass.isInstance(meta)) {
                  try {
                        Method setDamageMethod = metas.EnchantmentStorageMetaClass.getMethod("addStoredEnchant", Enchantment.class,Integer.class,Boolean.class);
                        setDamageMethod.invoke(meta, enchantment, entry.getValue(), true);
                  } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
                        e.printStackTrace();
                  }
                }
            }
            if (instance(meta,metas.FireworkEffectMetaClass)) classSet(metas.FireworkEffectMetaClass,"setEffect",this.FireworkEffectMeta,meta);
            if (instance(meta,metas.FireworkMetaClass)) classSet(metas.FireworkMetaClass,"setEffects",this.FireworkMeta,meta);
            if (instance(meta,metas.KnowledgeBookMetaClass)) classSet(metas.KnowledgeBookMetaClass,"setRecipes",this.KnowledgeBookMeta,meta);
            if (instance(meta,metas.LeatherArmorMetaClass)) classSet(metas.LeatherArmorMetaClass,"setColor",this.LeatherArmorMeta,meta);
            if (instance(meta,metas.MapMetaClass)) {
                classSet(metas.MapMetaClass, "setColor",this.MapMetaColor, meta);
                classSet(metas.MapMetaClass, "setColor",this.MapMetaMapView, meta);
            }
            if (instance(meta,metas.RepairableClass)) classSet(metas.RepairableClass, "setRepairCost",this.Repairable, meta);
            if (instance(meta,metas.SkullMetaClass)) classSet(metas.SkullMetaClass,"setOwningPlayer",this.SkullMetaOfflinePlayer,meta);
            if (instance(meta,metas.SuspiciousStewMetaClass)) classSet(metas.SuspiciousStewMetaClass,"setCustomEffects",this.SuspiciousStewMeta,meta);
            if (instance(meta,metas.TropicalFishBucketMetaClass)) {
                classSet(metas.TropicalFishBucketMetaClass,"setPattern",this.TropicalFishBucketMetaPattern,meta);
                classSet(metas.TropicalFishBucketMetaClass,"setBodyColor",this.TropicalFishBucketMetaBodyColor,meta);
                classSet(metas.TropicalFishBucketMetaClass,"setPatternColor",this.TropicalFishBucketMetaPatternColor,meta);
            }
            if (instance(meta,metas.BookMetaClass)) {
                classSet(metas.BookMetaClass, "setAuthor",this.BookMetaAuthor, meta);
                classSet(metas.BookMetaClass, "setGeneration",this.BookMetaGeneration, meta);
                classSet(metas.BookMetaClass, "setPages",this.BookMetaPages, meta);
                classSet(metas.BookMetaClass, "setTitle",this.BookMetaTitle, meta);
            }
            this.lore = Objects.requireNonNull(meta).hasLore() ? new ArrayList<>(Objects.requireNonNull(meta.getLore())) : null;
            this.displayName = meta.hasDisplayName() ? meta.getDisplayName() : null;
            if (instance(meta,metas.DamageableClass) && this.Damageable > 0) classSet(metas.DamageableClass,"setDamage",this.Damageable,meta);
            if (instance(meta,metas.PotionMetaClass) && this.PotionEffectType != null) {
                if (this.type.equals(Material.POTION) || this.type.equals(Material.LINGERING_POTION) || this.type.equals(Material.SPLASH_POTION)) {
                  if (metas.PotionTypeClass != null) {
                        try {
                            Constructor<?> potionDataConstructor = metas.PotionTypeClass.getConstructor(metas.PotionEffectType, boolean.class, boolean.class);
                            Method setBasePotionDataMethod = metas.PotionMetaClass.getMethod("setBasePotionData", metas.PotionTypeClass);
                            if (metas.PotionEffectType != null) {
                              setBasePotionDataMethod.invoke(meta, potionDataConstructor.newInstance(
                                        metas.PotionEffectType.getMethod("getByName", String.class).invoke(this.PotionEffectType),
                                        !isSplash && this.PotionIsExtendable,
                                        isSplash && this.PotionIsUpgradeable
                              ));
                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                  }
                }
            }
            if (instance(meta,metas.AxolotlBucketMetaClass) && this.Variant != null) {
                classSet(metas.AxolotlBucketMetaClass,"setVariant",this.Variant,meta);
            }
            if (instance(meta,metas.CompassMetaClass) && this.CompassMeta != null) {
                classSet(metas.CompassMetaClass,"setLodestone",this.CompassMeta.toLocation(),meta);
            }
            if (instance(meta,metas.FireworkEffectMetaClass) && this.FireworkEffectMeta != null) {
                classSet(metas.FireworkEffectMetaClass,"setEffect",this.FireworkEffectMeta,meta);
            }
            if (instance(meta,metas.FireworkMetaClass) && this.FireworkMeta != null) {
                classSet(metas.FireworkMetaClass,"addEffects",this.FireworkMeta,meta);
            }
            if (instance(meta,metas.KnowledgeBookMetaClass) && this.KnowledgeBookMeta != null) {
                classSet(metas.KnowledgeBookMetaClass,"setRecipes",this.KnowledgeBookMeta,meta);
            }
            if (instance(meta,metas.LeatherArmorMetaClass) && this.LeatherArmorMeta != null) {
                classSet(metas.LeatherArmorMetaClass,"setColor",this.LeatherArmorMeta,meta);
            }
            if (instance(meta,metas.MapMetaClass)) {

                if (this.MapMetaColor != null) classSet(metas.MapMetaClass,"setColor",this.MapMetaColor,meta);
                if (this.MapMetaMapView != null) classSet(metas.MapMetaClass,"setMapView",this.MapMetaMapView,meta);
            }
            if (instance(meta,metas.RepairableClass) && this.Repairable > 0) {
                classSet(metas.RepairableClass,"setRepairCost",this.Repairable,meta);
            }
            if (instance(meta,metas.SkullMetaClass) && this.SkullMetaOfflinePlayer != null) {
                classSet(metas.SkullMetaClass,"setOwningPlayer",this.SkullMetaOfflinePlayer,meta);
            }
            if (instance(meta,metas.SuspiciousStewMetaClass) && this.SuspiciousStewMeta != null) {
                for (Object data : this.SuspiciousStewMeta)
                  if (data != null && metas.SuspiciousStewMetaClass.isInstance(meta)) {
                  try {
                        Method setDamageMethod = metas.SuspiciousStewMetaClass.getMethod("addCustomEffect", Object.class,Boolean.class);
                        setDamageMethod.invoke(meta, data, true);
                  } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
                        e.printStackTrace();
                  }
                }
            }
            if (instance(meta,metas.TropicalFishBucketMetaClass)) {
                if (this.TropicalFishBucketMetaBodyColor != null) classSet(metas.TropicalFishBucketMetaClass,"setBodyColor",this.TropicalFishBucketMetaBodyColor,meta);
                if (this.TropicalFishBucketMetaPattern != null) classSet(metas.TropicalFishBucketMetaClass,"setPattern",this.TropicalFishBucketMetaPattern,meta);
                if (this.TropicalFishBucketMetaPatternColor != null) classSet(metas.TropicalFishBucketMetaClass,"setPatternColor",this.TropicalFishBucketMetaPatternColor,meta);
            }
            if (instance(meta,metas.BookMetaClass)) {
                if (this.BookMetaAuthor != null) classSet(metas.BookMetaClass,"setAuthor",this.BookMetaAuthor,meta);
                if (this.BookMetaGeneration != null) classSet(metas.BookMetaClass,"setGeneration",this.BookMetaGeneration,meta);
                if (this.BookMetaPages != null) classSet(metas.BookMetaClass,"setPages",this.BookMetaPages,meta);
                if (this.BookMetaTitle != null) classSet(metas.BookMetaClass,"setTitle",this.BookMetaTitle,meta);
            }
      }
      return meta;
    }
    public static boolean instance(ItemMeta meta,Class<?> clazz) {
      return clazz != null && clazz.isInstance(meta);
    }
    public static class Location implements Serializable {
      private final double x;
      private final double y;
      private final double z;
      private final World world;
      public Location(org.bukkit.Location location) {
            this.world = location.getWorld();
            this.x = location.getX();
            this.y = location.getY();
            this.z = location.getZ();
      }
      public org.bukkit.Location toLocation() {
            return new org.bukkit.Location(this.world,this.x,this.y,this.z);
      }
    }
}

AcesDephtPest 发表于 2024-8-30 20:17:57

最后修改的代码:第二页
作者放弃时间:2024/8/3020:17
问题描述:基本上全部报错,无法映射

AcesDephtPest 发表于 2024-8-28 21:28:35

代码那个是只显示一格,还请见谅
页: [1]
查看完整版本: ItemStack(映射版,但是是NBT丢失)