minecraft-src/net/minecraft/world/item/ArmorItem.java
2025-07-04 01:41:11 +03:00

169 lines
6 KiB
Java

package net.minecraft.world.item;
import com.google.common.base.Suppliers;
import com.mojang.serialization.Codec;
import java.util.List;
import java.util.function.Supplier;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.core.dispenser.BlockSource;
import net.minecraft.core.dispenser.DefaultDispenseItemBehavior;
import net.minecraft.core.dispenser.DispenseItemBehavior;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.util.StringRepresentable;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResultHolder;
import net.minecraft.world.entity.EntitySelector;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.EquipmentSlotGroup;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.entity.ai.attributes.AttributeModifier;
import net.minecraft.world.entity.ai.attributes.Attributes;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.component.ItemAttributeModifiers;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.DispenserBlock;
import net.minecraft.world.phys.AABB;
public class ArmorItem extends Item implements Equipable {
public static final DispenseItemBehavior DISPENSE_ITEM_BEHAVIOR = new DefaultDispenseItemBehavior() {
@Override
protected ItemStack execute(BlockSource blockSource, ItemStack item) {
return ArmorItem.dispenseArmor(blockSource, item) ? item : super.execute(blockSource, item);
}
};
protected final ArmorItem.Type type;
protected final Holder<ArmorMaterial> material;
private final Supplier<ItemAttributeModifiers> defaultModifiers;
public static boolean dispenseArmor(BlockSource blockSource, ItemStack armorItem) {
BlockPos blockPos = blockSource.pos().relative(blockSource.state().getValue(DispenserBlock.FACING));
List<LivingEntity> list = blockSource.level()
.getEntitiesOfClass(LivingEntity.class, new AABB(blockPos), EntitySelector.NO_SPECTATORS.and(new EntitySelector.MobCanWearArmorEntitySelector(armorItem)));
if (list.isEmpty()) {
return false;
} else {
LivingEntity livingEntity = (LivingEntity)list.get(0);
EquipmentSlot equipmentSlot = livingEntity.getEquipmentSlotForItem(armorItem);
ItemStack itemStack = armorItem.split(1);
livingEntity.setItemSlot(equipmentSlot, itemStack);
if (livingEntity instanceof Mob) {
((Mob)livingEntity).setDropChance(equipmentSlot, 2.0F);
((Mob)livingEntity).setPersistenceRequired();
}
return true;
}
}
public ArmorItem(Holder<ArmorMaterial> material, ArmorItem.Type type, Item.Properties properties) {
super(properties);
this.material = material;
this.type = type;
DispenserBlock.registerBehavior(this, DISPENSE_ITEM_BEHAVIOR);
this.defaultModifiers = Suppliers.memoize(() -> {
int i = material.value().getDefense(type);
float f = material.value().toughness();
ItemAttributeModifiers.Builder builder = ItemAttributeModifiers.builder();
EquipmentSlotGroup equipmentSlotGroup = EquipmentSlotGroup.bySlot(type.getSlot());
ResourceLocation resourceLocation = ResourceLocation.withDefaultNamespace("armor." + type.getName());
builder.add(Attributes.ARMOR, new AttributeModifier(resourceLocation, i, AttributeModifier.Operation.ADD_VALUE), equipmentSlotGroup);
builder.add(Attributes.ARMOR_TOUGHNESS, new AttributeModifier(resourceLocation, f, AttributeModifier.Operation.ADD_VALUE), equipmentSlotGroup);
float g = material.value().knockbackResistance();
if (g > 0.0F) {
builder.add(Attributes.KNOCKBACK_RESISTANCE, new AttributeModifier(resourceLocation, g, AttributeModifier.Operation.ADD_VALUE), equipmentSlotGroup);
}
return builder.build();
});
}
public ArmorItem.Type getType() {
return this.type;
}
@Override
public int getEnchantmentValue() {
return this.material.value().enchantmentValue();
}
public Holder<ArmorMaterial> getMaterial() {
return this.material;
}
@Override
public boolean isValidRepairItem(ItemStack stack, ItemStack repairCandidate) {
return ((Ingredient)this.material.value().repairIngredient().get()).test(repairCandidate) || super.isValidRepairItem(stack, repairCandidate);
}
@Override
public InteractionResultHolder<ItemStack> use(Level level, Player player, InteractionHand usedHand) {
return this.swapWithEquipmentSlot(this, level, player, usedHand);
}
@Override
public ItemAttributeModifiers getDefaultAttributeModifiers() {
return (ItemAttributeModifiers)this.defaultModifiers.get();
}
public int getDefense() {
return this.material.value().getDefense(this.type);
}
public float getToughness() {
return this.material.value().toughness();
}
@Override
public EquipmentSlot getEquipmentSlot() {
return this.type.getSlot();
}
@Override
public Holder<SoundEvent> getEquipSound() {
return this.getMaterial().value().equipSound();
}
public static enum Type implements StringRepresentable {
HELMET(EquipmentSlot.HEAD, 11, "helmet"),
CHESTPLATE(EquipmentSlot.CHEST, 16, "chestplate"),
LEGGINGS(EquipmentSlot.LEGS, 15, "leggings"),
BOOTS(EquipmentSlot.FEET, 13, "boots"),
BODY(EquipmentSlot.BODY, 16, "body");
public static final Codec<ArmorItem.Type> CODEC = StringRepresentable.fromValues(ArmorItem.Type::values);
private final EquipmentSlot slot;
private final String name;
private final int durability;
private Type(final EquipmentSlot slot, final int durability, final String name) {
this.slot = slot;
this.name = name;
this.durability = durability;
}
public int getDurability(int durabilityFactor) {
return this.durability * durabilityFactor;
}
public EquipmentSlot getSlot() {
return this.slot;
}
public String getName() {
return this.name;
}
public boolean hasTrims() {
return this == HELMET || this == CHESTPLATE || this == LEGGINGS || this == BOOTS;
}
@Override
public String getSerializedName() {
return this.name;
}
}
}