package net.minecraft.world.item;

import java.util.AbstractList;
import net.minecraft.Util;
import org.apache.logging.log4j.LogManager;
import com.mojang.datafixers.kinds.Applicative;
import com.mojang.datafixers.kinds.App;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import java.text.DecimalFormatSymbols;
import java.util.Locale;
import net.minecraft.sounds.SoundEvent;
import java.util.function.Predicate;
import net.minecraft.commands.arguments.blocks.BlockPredicateArgument;
import net.minecraft.tags.TagManager;
import java.util.Objects;
import net.minecraft.network.chat.HoverEvent;
import com.google.common.collect.HashMultimap;
import net.minecraft.world.entity.decoration.ItemFrame;
import net.minecraft.world.item.enchantment.Enchantment;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import java.util.stream.Collector;
import java.util.stream.Collectors;
import java.util.function.Function;
import net.minecraft.world.level.block.Block;
import net.minecraft.tags.BlockTags;
import net.minecraft.commands.arguments.blocks.BlockStateParser;
import com.mojang.brigadier.StringReader;
import java.util.Iterator;
import com.google.common.collect.Multimap;
import net.minecraft.network.chat.MutableComponent;
import java.util.Collection;
import net.minecraft.world.entity.MobType;
import net.minecraft.world.entity.ai.attributes.Attributes;
import net.minecraft.world.entity.ai.attributes.AttributeModifier;
import net.minecraft.world.entity.ai.attributes.Attribute;
import java.util.Map;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.network.chat.ComponentUtils;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.TextComponent;
import com.google.common.collect.Lists;
import java.util.List;
import com.google.gson.JsonParseException;
import net.minecraft.network.chat.Component;
import net.minecraft.nbt.ListTag;
import net.minecraft.advancements.CriteriaTriggers;
import net.minecraft.world.item.enchantment.DigDurabilityEnchantment;
import net.minecraft.world.item.enchantment.EnchantmentHelper;
import net.minecraft.world.item.enchantment.Enchantments;
import javax.annotation.Nullable;
import net.minecraft.server.level.ServerPlayer;
import java.util.Random;
import net.minecraft.nbt.Tag;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.InteractionResultHolder;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.player.Player;
import net.minecraft.stats.Stat;
import net.minecraft.stats.Stats;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.InteractionResult;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.core.Registry;
import java.util.function.Consumer;
import java.util.Optional;
import net.minecraft.world.level.ItemLike;
import net.minecraft.world.level.block.state.pattern.BlockInWorld;
import net.minecraft.world.entity.Entity;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Style;
import java.text.DecimalFormat;
import org.apache.logging.log4j.Logger;
import com.mojang.serialization.Codec;

public final class ItemStack {
    public static final Codec<ItemStack> CODEC;
    private static final Logger LOGGER;
    public static final ItemStack EMPTY;
    public static final DecimalFormat ATTRIBUTE_MODIFIER_FORMAT;
    private static final Style LORE_STYLE;
    private int count;
    private int popTime;
    @Deprecated
    private final Item item;
    private CompoundTag tag;
    private boolean emptyCacheFlag;
    private Entity entityRepresentation;
    private BlockInWorld cachedBreakBlock;
    private boolean cachedBreakBlockResult;
    private BlockInWorld cachedPlaceBlock;
    private boolean cachedPlaceBlockResult;
    
    public ItemStack(final ItemLike bqa) {
        this(bqa, 1);
    }
    
    private ItemStack(final ItemLike bqa, final int integer, final Optional<CompoundTag> optional) {
        this(bqa, integer);
        optional.ifPresent(this::setTag);
    }
    
    public ItemStack(final ItemLike bqa, final int integer) {
        this.item = ((bqa == null) ? null : bqa.asItem());
        this.count = integer;
        if (this.item != null && this.item.canBeDepleted()) {
            this.setDamageValue(this.getDamageValue());
        }
        this.updateEmptyCacheFlag();
    }
    
    private void updateEmptyCacheFlag() {
        this.emptyCacheFlag = false;
        this.emptyCacheFlag = this.isEmpty();
    }
    
    private ItemStack(final CompoundTag le) {
        this.item = Registry.ITEM.get(new ResourceLocation(le.getString("id")));
        this.count = le.getByte("Count");
        if (le.contains("tag", 10)) {
            this.tag = le.getCompound("tag");
            this.getItem().verifyTagAfterLoad(le);
        }
        if (this.getItem().canBeDepleted()) {
            this.setDamageValue(this.getDamageValue());
        }
        this.updateEmptyCacheFlag();
    }
    
    public static ItemStack of(final CompoundTag le) {
        try {
            return new ItemStack(le);
        }
        catch (RuntimeException runtimeException2) {
            ItemStack.LOGGER.debug("Tried to load invalid item: {}", le, runtimeException2);
            return ItemStack.EMPTY;
        }
    }
    
    public boolean isEmpty() {
        return this == ItemStack.EMPTY || (this.getItem() == null || this.getItem() == Items.AIR) || this.count <= 0;
    }
    
    public ItemStack split(final int integer) {
        final int integer2 = Math.min(integer, this.count);
        final ItemStack bki4 = this.copy();
        bki4.setCount(integer2);
        this.shrink(integer2);
        return bki4;
    }
    
    public Item getItem() {
        return this.emptyCacheFlag ? Items.AIR : this.item;
    }
    
    public InteractionResult useOn(final UseOnContext blv) {
        final Player bec3 = blv.getPlayer();
        final BlockPos fu4 = blv.getClickedPos();
        final BlockInWorld cfn5 = new BlockInWorld(blv.getLevel(), fu4, false);
        if (bec3 != null && !bec3.abilities.mayBuild && !this.hasAdventureModePlaceTagForBlock(blv.getLevel().getTagManager(), cfn5)) {
            return InteractionResult.PASS;
        }
        final Item bke6 = this.getItem();
        final InteractionResult ang7 = bke6.useOn(blv);
        if (bec3 != null && ang7.consumesAction()) {
            bec3.awardStat(Stats.ITEM_USED.get(bke6));
        }
        return ang7;
    }
    
    public float getDestroySpeed(final BlockState cfj) {
        return this.getItem().getDestroySpeed(this, cfj);
    }
    
    public InteractionResultHolder<ItemStack> use(final Level bqb, final Player bec, final InteractionHand anf) {
        return this.getItem().use(bqb, bec, anf);
    }
    
    public ItemStack finishUsingItem(final Level bqb, final LivingEntity aoy) {
        return this.getItem().finishUsingItem(this, bqb, aoy);
    }
    
    public CompoundTag save(final CompoundTag le) {
        final ResourceLocation uh3 = Registry.ITEM.getKey(this.getItem());
        le.putString("id", (uh3 == null) ? "minecraft:air" : uh3.toString());
        le.putByte("Count", (byte)this.count);
        if (this.tag != null) {
            le.put("tag", this.tag.copy());
        }
        return le;
    }
    
    public int getMaxStackSize() {
        return this.getItem().getMaxStackSize();
    }
    
    public boolean isStackable() {
        return this.getMaxStackSize() > 1 && (!this.isDamageableItem() || !this.isDamaged());
    }
    
    public boolean isDamageableItem() {
        if (this.emptyCacheFlag || this.getItem().getMaxDamage() <= 0) {
            return false;
        }
        final CompoundTag le2 = this.getTag();
        return le2 == null || !le2.getBoolean("Unbreakable");
    }
    
    public boolean isDamaged() {
        return this.isDamageableItem() && this.getDamageValue() > 0;
    }
    
    public int getDamageValue() {
        return (this.tag == null) ? 0 : this.tag.getInt("Damage");
    }
    
    public void setDamageValue(final int integer) {
        this.getOrCreateTag().putInt("Damage", Math.max(0, integer));
    }
    
    public int getMaxDamage() {
        return this.getItem().getMaxDamage();
    }
    
    public boolean hurt(int integer, final Random random, @Nullable final ServerPlayer ze) {
        if (!this.isDamageableItem()) {
            return false;
        }
        if (integer > 0) {
            final int integer2 = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.UNBREAKING, this);
            int integer3 = 0;
            for (int integer4 = 0; integer2 > 0 && integer4 < integer; ++integer4) {
                if (DigDurabilityEnchantment.shouldIgnoreDurabilityDrop(this, integer2, random)) {
                    ++integer3;
                }
            }
            integer -= integer3;
            if (integer <= 0) {
                return false;
            }
        }
        if (ze != null && integer != 0) {
            CriteriaTriggers.ITEM_DURABILITY_CHANGED.trigger(ze, this, this.getDamageValue() + integer);
        }
        final int integer2 = this.getDamageValue() + integer;
        this.setDamageValue(integer2);
        return integer2 >= this.getMaxDamage();
    }
    
    public <T extends LivingEntity> void hurtAndBreak(final int integer, final T aoy, final Consumer<T> consumer) {
        if (aoy.level.isClientSide || (aoy instanceof Player && ((Player)aoy).abilities.instabuild)) {
            return;
        }
        if (!this.isDamageableItem()) {
            return;
        }
        if (this.hurt(integer, aoy.getRandom(), (aoy instanceof ServerPlayer) ? aoy : null)) {
            consumer.accept(aoy);
            final Item bke5 = this.getItem();
            this.shrink(1);
            if (aoy instanceof Player) {
                ((Player)aoy).awardStat(Stats.ITEM_BROKEN.get(bke5));
            }
            this.setDamageValue(0);
        }
    }
    
    public void hurtEnemy(final LivingEntity aoy, final Player bec) {
        final Item bke4 = this.getItem();
        if (bke4.hurtEnemy(this, aoy, bec)) {
            bec.awardStat(Stats.ITEM_USED.get(bke4));
        }
    }
    
    public void mineBlock(final Level bqb, final BlockState cfj, final BlockPos fu, final Player bec) {
        final Item bke6 = this.getItem();
        if (bke6.mineBlock(this, bqb, cfj, fu, bec)) {
            bec.awardStat(Stats.ITEM_USED.get(bke6));
        }
    }
    
    public boolean isCorrectToolForDrops(final BlockState cfj) {
        return this.getItem().isCorrectToolForDrops(cfj);
    }
    
    public InteractionResult interactLivingEntity(final Player bec, final LivingEntity aoy, final InteractionHand anf) {
        return this.getItem().interactLivingEntity(this, bec, aoy, anf);
    }
    
    public ItemStack copy() {
        if (this.isEmpty()) {
            return ItemStack.EMPTY;
        }
        final ItemStack bki2 = new ItemStack(this.getItem(), this.count);
        bki2.setPopTime(this.getPopTime());
        if (this.tag != null) {
            bki2.tag = this.tag.copy();
        }
        return bki2;
    }
    
    public static boolean tagMatches(final ItemStack bki1, final ItemStack bki2) {
        return (bki1.isEmpty() && bki2.isEmpty()) || (!bki1.isEmpty() && !bki2.isEmpty() && (bki1.tag != null || bki2.tag == null) && (bki1.tag == null || bki1.tag.equals(bki2.tag)));
    }
    
    public static boolean matches(final ItemStack bki1, final ItemStack bki2) {
        return (bki1.isEmpty() && bki2.isEmpty()) || (!bki1.isEmpty() && !bki2.isEmpty() && bki1.matches(bki2));
    }
    
    private boolean matches(final ItemStack bki) {
        return this.count == bki.count && this.getItem() == bki.getItem() && (this.tag != null || bki.tag == null) && (this.tag == null || this.tag.equals(bki.tag));
    }
    
    public static boolean isSame(final ItemStack bki1, final ItemStack bki2) {
        return bki1 == bki2 || (!bki1.isEmpty() && !bki2.isEmpty() && bki1.sameItem(bki2));
    }
    
    public static boolean isSameIgnoreDurability(final ItemStack bki1, final ItemStack bki2) {
        return bki1 == bki2 || (!bki1.isEmpty() && !bki2.isEmpty() && bki1.sameItemStackIgnoreDurability(bki2));
    }
    
    public boolean sameItem(final ItemStack bki) {
        return !bki.isEmpty() && this.getItem() == bki.getItem();
    }
    
    public boolean sameItemStackIgnoreDurability(final ItemStack bki) {
        if (this.isDamageableItem()) {
            return !bki.isEmpty() && this.getItem() == bki.getItem();
        }
        return this.sameItem(bki);
    }
    
    public String getDescriptionId() {
        return this.getItem().getDescriptionId(this);
    }
    
    @Override
    public String toString() {
        return this.count + " " + this.getItem();
    }
    
    public void inventoryTick(final Level bqb, final Entity aom, final int integer, final boolean boolean4) {
        if (this.popTime > 0) {
            --this.popTime;
        }
        if (this.getItem() != null) {
            this.getItem().inventoryTick(this, bqb, aom, integer, boolean4);
        }
    }
    
    public void onCraftedBy(final Level bqb, final Player bec, final int integer) {
        bec.awardStat(Stats.ITEM_CRAFTED.get(this.getItem()), integer);
        this.getItem().onCraftedBy(this, bqb, bec);
    }
    
    public int getUseDuration() {
        return this.getItem().getUseDuration(this);
    }
    
    public UseAnim getUseAnimation() {
        return this.getItem().getUseAnimation(this);
    }
    
    public void releaseUsing(final Level bqb, final LivingEntity aoy, final int integer) {
        this.getItem().releaseUsing(this, bqb, aoy, integer);
    }
    
    public boolean useOnRelease() {
        return this.getItem().useOnRelease(this);
    }
    
    public boolean hasTag() {
        return !this.emptyCacheFlag && this.tag != null && !this.tag.isEmpty();
    }
    
    @Nullable
    public CompoundTag getTag() {
        return this.tag;
    }
    
    public CompoundTag getOrCreateTag() {
        if (this.tag == null) {
            this.setTag(new CompoundTag());
        }
        return this.tag;
    }
    
    public CompoundTag getOrCreateTagElement(final String string) {
        if (this.tag == null || !this.tag.contains(string, 10)) {
            final CompoundTag le3 = new CompoundTag();
            this.addTagElement(string, le3);
            return le3;
        }
        return this.tag.getCompound(string);
    }
    
    @Nullable
    public CompoundTag getTagElement(final String string) {
        if (this.tag == null || !this.tag.contains(string, 10)) {
            return null;
        }
        return this.tag.getCompound(string);
    }
    
    public void removeTagKey(final String string) {
        if (this.tag != null && this.tag.contains(string)) {
            this.tag.remove(string);
            if (this.tag.isEmpty()) {
                this.tag = null;
            }
        }
    }
    
    public ListTag getEnchantmentTags() {
        if (this.tag != null) {
            return this.tag.getList("Enchantments", 10);
        }
        return new ListTag();
    }
    
    public void setTag(@Nullable final CompoundTag le) {
        this.tag = le;
        if (this.getItem().canBeDepleted()) {
            this.setDamageValue(this.getDamageValue());
        }
    }
    
    public Component getHoverName() {
        final CompoundTag le2 = this.getTagElement("display");
        if (le2 != null && le2.contains("Name", 8)) {
            try {
                final Component mr3 = Component.Serializer.fromJson(le2.getString("Name"));
                if (mr3 != null) {
                    return mr3;
                }
                le2.remove("Name");
            }
            catch (JsonParseException jsonParseException3) {
                le2.remove("Name");
            }
        }
        return this.getItem().getName(this);
    }
    
    public ItemStack setHoverName(@Nullable final Component mr) {
        final CompoundTag le3 = this.getOrCreateTagElement("display");
        if (mr != null) {
            le3.putString("Name", Component.Serializer.toJson(mr));
        }
        else {
            le3.remove("Name");
        }
        return this;
    }
    
    public void resetHoverName() {
        final CompoundTag le2 = this.getTagElement("display");
        if (le2 != null) {
            le2.remove("Name");
            if (le2.isEmpty()) {
                this.removeTagKey("display");
            }
        }
        if (this.tag != null && this.tag.isEmpty()) {
            this.tag = null;
        }
    }
    
    public boolean hasCustomHoverName() {
        final CompoundTag le2 = this.getTagElement("display");
        return le2 != null && le2.contains("Name", 8);
    }
    
    public List<Component> getTooltipLines(@Nullable final Player bec, final TooltipFlag bls) {
        final List<Component> list4 = Lists.newArrayList();
        final MutableComponent mx5 = new TextComponent("").append(this.getHoverName()).withStyle(this.getRarity().color);
        if (this.hasCustomHoverName()) {
            mx5.withStyle(ChatFormatting.ITALIC);
        }
        list4.add(mx5);
        if (!bls.isAdvanced() && !this.hasCustomHoverName() && this.getItem() == Items.FILLED_MAP) {
            list4.add(new TextComponent("#" + MapItem.getMapId(this)).withStyle(ChatFormatting.GRAY));
        }
        int integer6 = 0;
        if (this.hasTag() && this.tag.contains("HideFlags", 99)) {
            integer6 = this.tag.getInt("HideFlags");
        }
        if ((integer6 & 0x20) == 0x0) {
            this.getItem().appendHoverText(this, (bec == null) ? null : bec.level, list4, bls);
        }
        if (this.hasTag()) {
            if ((integer6 & 0x1) == 0x0) {
                appendEnchantmentNames(list4, this.getEnchantmentTags());
            }
            if (this.tag.contains("display", 10)) {
                final CompoundTag le7 = this.tag.getCompound("display");
                if (le7.contains("color", 3)) {
                    if (bls.isAdvanced()) {
                        list4.add(new TranslatableComponent("item.color", new Object[] { String.format("#%06X", le7.getInt("color")) }).withStyle(ChatFormatting.GRAY));
                    }
                    else {
                        list4.add(new TranslatableComponent("item.dyed").withStyle(ChatFormatting.GRAY, ChatFormatting.ITALIC));
                    }
                }
                if (le7.getTagType("Lore") == 9) {
                    final ListTag lk8 = le7.getList("Lore", 8);
                    for (int integer7 = 0; integer7 < lk8.size(); ++integer7) {
                        final String string10 = lk8.getString(integer7);
                        try {
                            final MutableComponent mx6 = Component.Serializer.fromJson(string10);
                            if (mx6 != null) {
                                list4.add(ComponentUtils.mergeStyles(mx6, ItemStack.LORE_STYLE));
                            }
                        }
                        catch (JsonParseException jsonParseException11) {
                            le7.remove("Lore");
                        }
                    }
                }
            }
        }
        for (final EquipmentSlot aor10 : EquipmentSlot.values()) {
            final Multimap<Attribute, AttributeModifier> multimap11 = this.getAttributeModifiers(aor10);
            if (!multimap11.isEmpty() && (integer6 & 0x2) == 0x0) {
                list4.add(TextComponent.EMPTY);
                list4.add(new TranslatableComponent("item.modifiers." + aor10.getName()).withStyle(ChatFormatting.GRAY));
                for (final Map.Entry<Attribute, AttributeModifier> entry13 : multimap11.entries()) {
                    final AttributeModifier apv14 = entry13.getValue();
                    double double15 = apv14.getAmount();
                    boolean boolean19 = false;
                    if (bec != null) {
                        if (apv14.getId() == Item.BASE_ATTACK_DAMAGE_UUID) {
                            double15 += bec.getAttributeBaseValue(Attributes.ATTACK_DAMAGE);
                            double15 += EnchantmentHelper.getDamageBonus(this, MobType.UNDEFINED);
                            boolean19 = true;
                        }
                        else if (apv14.getId() == Item.BASE_ATTACK_SPEED_UUID) {
                            double15 += bec.getAttributeBaseValue(Attributes.ATTACK_SPEED);
                            boolean19 = true;
                        }
                    }
                    double double16;
                    if (apv14.getOperation() == AttributeModifier.Operation.MULTIPLY_BASE || apv14.getOperation() == AttributeModifier.Operation.MULTIPLY_TOTAL) {
                        double16 = double15 * 100.0;
                    }
                    else if (entry13.getKey().equals(Attributes.KNOCKBACK_RESISTANCE)) {
                        double16 = double15 * 10.0;
                    }
                    else {
                        double16 = double15;
                    }
                    if (boolean19) {
                        list4.add(new TextComponent(" ").append(new TranslatableComponent("attribute.modifier.equals." + apv14.getOperation().toValue(), new Object[] { ItemStack.ATTRIBUTE_MODIFIER_FORMAT.format(double16), new TranslatableComponent(entry13.getKey().getDescriptionId()) })).withStyle(ChatFormatting.DARK_GREEN));
                    }
                    else if (double15 > 0.0) {
                        list4.add(new TranslatableComponent("attribute.modifier.plus." + apv14.getOperation().toValue(), new Object[] { ItemStack.ATTRIBUTE_MODIFIER_FORMAT.format(double16), new TranslatableComponent(entry13.getKey().getDescriptionId()) }).withStyle(ChatFormatting.BLUE));
                    }
                    else {
                        if (double15 >= 0.0) {
                            continue;
                        }
                        double16 *= -1.0;
                        list4.add(new TranslatableComponent("attribute.modifier.take." + apv14.getOperation().toValue(), new Object[] { ItemStack.ATTRIBUTE_MODIFIER_FORMAT.format(double16), new TranslatableComponent(entry13.getKey().getDescriptionId()) }).withStyle(ChatFormatting.RED));
                    }
                }
            }
        }
        if (this.hasTag() && this.getTag().getBoolean("Unbreakable") && (integer6 & 0x4) == 0x0) {
            list4.add(new TranslatableComponent("item.unbreakable").withStyle(ChatFormatting.BLUE));
        }
        if (this.hasTag() && this.tag.contains("CanDestroy", 9) && (integer6 & 0x8) == 0x0) {
            final ListTag lk9 = this.tag.getList("CanDestroy", 8);
            if (!lk9.isEmpty()) {
                list4.add(TextComponent.EMPTY);
                list4.add(new TranslatableComponent("item.canBreak").withStyle(ChatFormatting.GRAY));
                for (int integer8 = 0; integer8 < lk9.size(); ++integer8) {
                    list4.addAll(expandBlockState(lk9.getString(integer8)));
                }
            }
        }
        if (this.hasTag() && this.tag.contains("CanPlaceOn", 9) && (integer6 & 0x10) == 0x0) {
            final ListTag lk9 = this.tag.getList("CanPlaceOn", 8);
            if (!lk9.isEmpty()) {
                list4.add(TextComponent.EMPTY);
                list4.add(new TranslatableComponent("item.canPlace").withStyle(ChatFormatting.GRAY));
                for (int integer8 = 0; integer8 < lk9.size(); ++integer8) {
                    list4.addAll(expandBlockState(lk9.getString(integer8)));
                }
            }
        }
        if (bls.isAdvanced()) {
            if (this.isDamaged()) {
                list4.add(new TranslatableComponent("item.durability", new Object[] { this.getMaxDamage() - this.getDamageValue(), this.getMaxDamage() }));
            }
            list4.add(new TextComponent(Registry.ITEM.getKey(this.getItem()).toString()).withStyle(ChatFormatting.DARK_GRAY));
            if (this.hasTag()) {
                list4.add(new TranslatableComponent("item.nbt_tags", new Object[] { this.getTag().getAllKeys().size() }).withStyle(ChatFormatting.DARK_GRAY));
            }
        }
        return list4;
    }
    
    public static void appendEnchantmentNames(final List<Component> list, final ListTag lk) {
        for (int integer3 = 0; integer3 < lk.size(); ++integer3) {
            final CompoundTag le4 = lk.getCompound(integer3);
            Registry.ENCHANTMENT.getOptional(ResourceLocation.tryParse(le4.getString("id"))).ifPresent(bnw -> list.add(bnw.getFullname(le4.getInt("lvl"))));
        }
    }
    
    private static Collection<Component> expandBlockState(final String string) {
        try {
            final BlockStateParser ef2 = new BlockStateParser(new StringReader(string), true).parse(true);
            final BlockState cfj3 = ef2.getState();
            final ResourceLocation uh4 = ef2.getTag();
            final boolean boolean5 = cfj3 != null;
            final boolean boolean6 = uh4 != null;
            if (boolean5 || boolean6) {
                if (boolean5) {
                    return Lists.<Component>newArrayList(cfj3.getBlock().getName().withStyle(ChatFormatting.DARK_GRAY));
                }
                final net.minecraft.tags.Tag<Block> adf7 = BlockTags.getAllTags().getTag(uh4);
                if (adf7 != null) {
                    final Collection<Block> collection8 = adf7.getValues();
                    if (!collection8.isEmpty()) {
                        return collection8.stream().map(Block::getName).map(mx -> mx.withStyle(ChatFormatting.DARK_GRAY)).collect(Collectors.toList());
                    }
                }
            }
        }
        catch (CommandSyntaxException ex) {}
        return Lists.<Component>newArrayList(new TextComponent("missingno").withStyle(ChatFormatting.DARK_GRAY));
    }
    
    public boolean hasFoil() {
        return this.getItem().isFoil(this);
    }
    
    public Rarity getRarity() {
        return this.getItem().getRarity(this);
    }
    
    public boolean isEnchantable() {
        return this.getItem().isEnchantable(this) && !this.isEnchanted();
    }
    
    public void enchant(final Enchantment bnw, final int integer) {
        this.getOrCreateTag();
        if (!this.tag.contains("Enchantments", 9)) {
            this.tag.put("Enchantments", new ListTag());
        }
        final ListTag lk4 = this.tag.getList("Enchantments", 10);
        final CompoundTag le5 = new CompoundTag();
        le5.putString("id", String.valueOf(Registry.ENCHANTMENT.getKey(bnw)));
        le5.putShort("lvl", (byte)integer);
        ((AbstractList<CompoundTag>)lk4).add(le5);
    }
    
    public boolean isEnchanted() {
        return this.tag != null && this.tag.contains("Enchantments", 9) && !this.tag.getList("Enchantments", 10).isEmpty();
    }
    
    public void addTagElement(final String string, final Tag lu) {
        this.getOrCreateTag().put(string, lu);
    }
    
    public boolean isFramed() {
        return this.entityRepresentation instanceof ItemFrame;
    }
    
    public void setEntityRepresentation(@Nullable final Entity aom) {
        this.entityRepresentation = aom;
    }
    
    @Nullable
    public ItemFrame getFrame() {
        return (this.entityRepresentation instanceof ItemFrame) ? ((ItemFrame)this.getEntityRepresentation()) : null;
    }
    
    @Nullable
    public Entity getEntityRepresentation() {
        return this.emptyCacheFlag ? null : this.entityRepresentation;
    }
    
    public int getBaseRepairCost() {
        if (this.hasTag() && this.tag.contains("RepairCost", 3)) {
            return this.tag.getInt("RepairCost");
        }
        return 0;
    }
    
    public void setRepairCost(final int integer) {
        this.getOrCreateTag().putInt("RepairCost", integer);
    }
    
    public Multimap<Attribute, AttributeModifier> getAttributeModifiers(final EquipmentSlot aor) {
        Multimap<Attribute, AttributeModifier> multimap3;
        if (this.hasTag() && this.tag.contains("AttributeModifiers", 9)) {
            multimap3 = HashMultimap.create();
            final ListTag lk4 = this.tag.getList("AttributeModifiers", 10);
            for (int integer5 = 0; integer5 < lk4.size(); ++integer5) {
                final CompoundTag le6 = lk4.getCompound(integer5);
                if (!le6.contains("Slot", 8) || le6.getString("Slot").equals(aor.getName())) {
                    final Optional<Attribute> optional7 = Registry.ATTRIBUTE.getOptional(ResourceLocation.tryParse(le6.getString("AttributeName")));
                    if (optional7.isPresent()) {
                        final AttributeModifier apv8 = AttributeModifier.load(le6);
                        if (apv8 != null) {
                            if (apv8.getId().getLeastSignificantBits() != 0L && apv8.getId().getMostSignificantBits() != 0L) {
                                multimap3.put(optional7.get(), apv8);
                            }
                        }
                    }
                }
            }
        }
        else {
            multimap3 = this.getItem().getDefaultAttributeModifiers(aor);
        }
        return multimap3;
    }
    
    public void addAttributeModifier(final Attribute aps, final AttributeModifier apv, @Nullable final EquipmentSlot aor) {
        this.getOrCreateTag();
        if (!this.tag.contains("AttributeModifiers", 9)) {
            this.tag.put("AttributeModifiers", new ListTag());
        }
        final ListTag lk5 = this.tag.getList("AttributeModifiers", 10);
        final CompoundTag le6 = apv.save();
        le6.putString("AttributeName", Registry.ATTRIBUTE.getKey(aps).toString());
        if (aor != null) {
            le6.putString("Slot", aor.getName());
        }
        ((AbstractList<CompoundTag>)lk5).add(le6);
    }
    
    public Component getDisplayName() {
        final MutableComponent mx2 = new TextComponent("").append(this.getHoverName());
        if (this.hasCustomHoverName()) {
            mx2.withStyle(ChatFormatting.ITALIC);
        }
        final MutableComponent mx3 = ComponentUtils.wrapInSquareBrackets(mx2);
        if (!this.emptyCacheFlag) {
            final HoverEvent mv;
            mx3.withStyle(this.getRarity().color).withStyle(nb -> {
                new HoverEvent(HoverEvent.Action.SHOW_ITEM, new HoverEvent.ItemStackInfo(this));
                return nb.withHoverEvent(mv);
            });
        }
        return mx3;
    }
    
    private static boolean areSameBlocks(final BlockInWorld cfn1, @Nullable final BlockInWorld cfn2) {
        return cfn2 != null && cfn1.getState() == cfn2.getState() && ((cfn1.getEntity() == null && cfn2.getEntity() == null) || (cfn1.getEntity() != null && cfn2.getEntity() != null && Objects.equals(cfn1.getEntity().save(new CompoundTag()), cfn2.getEntity().save(new CompoundTag()))));
    }
    
    public boolean hasAdventureModeBreakTagForBlock(final TagManager adh, final BlockInWorld cfn) {
        if (areSameBlocks(cfn, this.cachedBreakBlock)) {
            return this.cachedBreakBlockResult;
        }
        this.cachedBreakBlock = cfn;
        if (this.hasTag() && this.tag.contains("CanDestroy", 9)) {
            final ListTag lk4 = this.tag.getList("CanDestroy", 8);
            for (int integer5 = 0; integer5 < lk4.size(); ++integer5) {
                final String string6 = lk4.getString(integer5);
                try {
                    final Predicate<BlockInWorld> predicate7 = BlockPredicateArgument.blockPredicate().parse(new StringReader(string6)).create(adh);
                    if (predicate7.test(cfn)) {
                        return this.cachedBreakBlockResult = true;
                    }
                }
                catch (CommandSyntaxException ex) {}
            }
        }
        return this.cachedBreakBlockResult = false;
    }
    
    public boolean hasAdventureModePlaceTagForBlock(final TagManager adh, final BlockInWorld cfn) {
        if (areSameBlocks(cfn, this.cachedPlaceBlock)) {
            return this.cachedPlaceBlockResult;
        }
        this.cachedPlaceBlock = cfn;
        if (this.hasTag() && this.tag.contains("CanPlaceOn", 9)) {
            final ListTag lk4 = this.tag.getList("CanPlaceOn", 8);
            for (int integer5 = 0; integer5 < lk4.size(); ++integer5) {
                final String string6 = lk4.getString(integer5);
                try {
                    final Predicate<BlockInWorld> predicate7 = BlockPredicateArgument.blockPredicate().parse(new StringReader(string6)).create(adh);
                    if (predicate7.test(cfn)) {
                        return this.cachedPlaceBlockResult = true;
                    }
                }
                catch (CommandSyntaxException ex) {}
            }
        }
        return this.cachedPlaceBlockResult = false;
    }
    
    public int getPopTime() {
        return this.popTime;
    }
    
    public void setPopTime(final int integer) {
        this.popTime = integer;
    }
    
    public int getCount() {
        return this.emptyCacheFlag ? 0 : this.count;
    }
    
    public void setCount(final int integer) {
        this.count = integer;
        this.updateEmptyCacheFlag();
    }
    
    public void grow(final int integer) {
        this.setCount(this.count + integer);
    }
    
    public void shrink(final int integer) {
        this.grow(-integer);
    }
    
    public void onUseTick(final Level bqb, final LivingEntity aoy, final int integer) {
        this.getItem().onUseTick(bqb, aoy, this, integer);
    }
    
    public boolean isEdible() {
        return this.getItem().isEdible();
    }
    
    public SoundEvent getDrinkingSound() {
        return this.getItem().getDrinkingSound();
    }
    
    public SoundEvent getEatingSound() {
        return this.getItem().getEatingSound();
    }
    
    static {
        CODEC = RecordCodecBuilder.create(instance -> ((RecordCodecBuilder.Instance)instance).group((App)Registry.ITEM.fieldOf("id").forGetter(bki -> bki.item), (App)Codec.INT.fieldOf("Count").forGetter(bki -> bki.count), (App)CompoundTag.CODEC.optionalFieldOf("tag").forGetter(bki -> Optional.<CompoundTag>ofNullable(bki.tag))).apply(instance, ItemStack::new));
        LOGGER = LogManager.getLogger();
        EMPTY = new ItemStack((ItemLike)null);
        ATTRIBUTE_MODIFIER_FORMAT = Util.<DecimalFormat>make(new DecimalFormat("#.##"), decimalFormat -> decimalFormat.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ROOT)));
        LORE_STYLE = Style.EMPTY.withColor(ChatFormatting.DARK_PURPLE).withItalic(true);
    }
}
