content: package emu.grasscutter.data.excels;
  
  import java.util.Arrays;
  import java.util.List;
  import java.util.Objects;
  
  import com.google.gson.annotations.SerializedName;
  import emu.grasscutter.data.GameResource;
  import emu.grasscutter.data.ResourceType;
  import emu.grasscutter.data.common.ItemUseData;
  import emu.grasscutter.game.inventory.*;
  import emu.grasscutter.game.props.FightProperty;
  import emu.grasscutter.game.props.ItemUseOp;
  import emu.grasscutter.game.props.ItemUseTarget;
  import emu.grasscutter.game.props.ItemUseAction.ItemUseAction;
  import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
  import it.unimi.dsi.fastutil.ints.IntSet;
  import lombok.Getter;
  
  @ResourceType(name = {"MaterialExcelConfigData.json",
          "WeaponExcelConfigData.json",
          "ReliquaryExcelConfigData.json",
          "HomeWorldFurnitureExcelConfigData.json"
  })
  @Getter
  public class ItemData extends GameResource {
      // Main
      @Getter(onMethod = @__(@Override))
      private int id;
      private int stackLimit = 1;
      private int maxUseCount;
      private int rankLevel;
      private String effectName;
      private int rank;
      private int weight;
      private int gadgetId;
  
      private int[] destroyReturnMaterial;
      private int[] destroyReturnMaterialCount;
  
      // Enums
      private ItemType itemType = ItemType.ITEM_NONE;
      private MaterialType materialType = MaterialType.MATERIAL_NONE;
      private EquipType equipType = EquipType.EQUIP_NONE;
      private String effectType;
      private String destroyRule;
  
      // Food
      private String foodQuality;
      private int[] satiationParams;
  
      // Usable item
      private ItemUseTarget useTarget = ItemUseTarget.ITEM_USE_TARGET_NONE;
      private List<ItemUseData> itemUse;
      private List<ItemUseAction> itemUseActions;
      private boolean useOnGain = false;
  
      // Relic
      private int mainPropDepotId;
      private int appendPropDepotId;
      private int appendPropNum;
      private int setId;
      private int[] addPropLevels;
      private int baseConvExp;
      private int maxLevel;
  
      // Weapon
      private int weaponPromoteId;
      private int weaponBaseExp;
      private int storyId;
      private int avatarPromoteId;
      private int awakenMaterial;
      private int[] awakenCosts;
      private int[] skillAffix;
      private WeaponProperty[] weaponProp;
  
      // Hash
      private long nameTextMapHash;
  
      // Furniture
      private int comfort;
      private List<Integer> furnType;
      private List<Integer> furnitureGadgetID;
  
      @SerializedName(value="roomSceneId", alternate={"BMEPAMCNABE", "DANFGGLKLNO", "JFDLJGDFIGL", "OHIANNAEEAK", "MFGACDIOHGF"})
      private int roomSceneId;
  
      // Custom
      private transient IntSet addPropLevelSet;
  
      public WeaponProperty[] getWeaponProperties() {
          return this.weaponProp;
      }
  
      public boolean canAddRelicProp(int level) {
          return this.addPropLevelSet != null && this.addPropLevelSet.contains(level);
      }
  
      public boolean isEquip() {
          return this.itemType == ItemType.ITEM_RELIQUARY || this.itemType == ItemType.ITEM_WEAPON;
      }
  
      @Override
      public void onLoad() {
          if (this.itemType == ItemType.ITEM_RELIQUARY) {
              if (this.addPropLevels != null && this.addPropLevels.length > 0) {
                  this.addPropLevelSet = new IntOpenHashSet(this.addPropLevels);
              }
          } else if (this.itemType == ItemType.ITEM_WEAPON) {
              this.equipType = EquipType.EQUIP_WEAPON;
          } else {
              this.equipType = EquipType.EQUIP_NONE;
          }
  
          if (this.weaponProp != null) {
              this.weaponProp = Arrays.stream(this.weaponProp).filter(prop -> prop.getPropType() != null).toArray(WeaponProperty[]::new);
          }
  
          if (this.getFurnType() != null) {
              this.furnType = this.furnType.stream().filter(x -> x > 0).toList();
          }
          if (this.getFurnitureGadgetID() != null) {
              this.furnitureGadgetID = this.furnitureGadgetID.stream().filter(x -> x > 0).toList();
          }
  
          // Prevent material type from being null
          this.materialType = this.materialType == null ? MaterialType.MATERIAL_NONE : this.materialType;
  
          if (this.itemUse != null && !this.itemUse.isEmpty()) {
              this.itemUseActions = this.itemUse.stream()
                                      .filter(x -> x.getUseOp() != ItemUseOp.ITEM_USE_NONE)
                                      .map(ItemUseAction::fromItemUseData)
                                      .filter(Objects::nonNull)
                                      .toList();
          }
      }
  
  
      @Getter
      public static class WeaponProperty {
          private FightProperty propType;
          private float initValue;
          private String type;
      }
  }
  