124 lines
4.8 KiB
Java
124 lines
4.8 KiB
Java
package net.minecraft.world.item.component;
|
|
|
|
import com.google.common.collect.ImmutableList;
|
|
import com.mojang.serialization.Codec;
|
|
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
|
import java.text.DecimalFormat;
|
|
import java.text.DecimalFormatSymbols;
|
|
import java.util.List;
|
|
import java.util.Locale;
|
|
import java.util.function.BiConsumer;
|
|
import net.minecraft.Util;
|
|
import net.minecraft.core.Holder;
|
|
import net.minecraft.network.RegistryFriendlyByteBuf;
|
|
import net.minecraft.network.codec.ByteBufCodecs;
|
|
import net.minecraft.network.codec.StreamCodec;
|
|
import net.minecraft.resources.ResourceLocation;
|
|
import net.minecraft.world.entity.EquipmentSlot;
|
|
import net.minecraft.world.entity.EquipmentSlotGroup;
|
|
import net.minecraft.world.entity.ai.attributes.Attribute;
|
|
import net.minecraft.world.entity.ai.attributes.AttributeModifier;
|
|
|
|
public record ItemAttributeModifiers(List<ItemAttributeModifiers.Entry> modifiers) {
|
|
public static final ItemAttributeModifiers EMPTY = new ItemAttributeModifiers(List.of());
|
|
public static final Codec<ItemAttributeModifiers> CODEC = ItemAttributeModifiers.Entry.CODEC
|
|
.listOf()
|
|
.xmap(ItemAttributeModifiers::new, ItemAttributeModifiers::modifiers);
|
|
public static final StreamCodec<RegistryFriendlyByteBuf, ItemAttributeModifiers> STREAM_CODEC = StreamCodec.composite(
|
|
ItemAttributeModifiers.Entry.STREAM_CODEC.apply(ByteBufCodecs.list()), ItemAttributeModifiers::modifiers, ItemAttributeModifiers::new
|
|
);
|
|
public static final DecimalFormat ATTRIBUTE_MODIFIER_FORMAT = Util.make(
|
|
new DecimalFormat("#.##"), decimalFormat -> decimalFormat.setDecimalFormatSymbols(DecimalFormatSymbols.getInstance(Locale.ROOT))
|
|
);
|
|
|
|
public static ItemAttributeModifiers.Builder builder() {
|
|
return new ItemAttributeModifiers.Builder();
|
|
}
|
|
|
|
public ItemAttributeModifiers withModifierAdded(Holder<Attribute> attribute, AttributeModifier modifier, EquipmentSlotGroup slot) {
|
|
ImmutableList.Builder<ItemAttributeModifiers.Entry> builder = ImmutableList.builderWithExpectedSize(this.modifiers.size() + 1);
|
|
|
|
for (ItemAttributeModifiers.Entry entry : this.modifiers) {
|
|
if (!entry.matches(attribute, modifier.id())) {
|
|
builder.add(entry);
|
|
}
|
|
}
|
|
|
|
builder.add(new ItemAttributeModifiers.Entry(attribute, modifier, slot));
|
|
return new ItemAttributeModifiers(builder.build());
|
|
}
|
|
|
|
public void forEach(EquipmentSlotGroup slotGroup, BiConsumer<Holder<Attribute>, AttributeModifier> action) {
|
|
for (ItemAttributeModifiers.Entry entry : this.modifiers) {
|
|
if (entry.slot.equals(slotGroup)) {
|
|
action.accept(entry.attribute, entry.modifier);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void forEach(EquipmentSlot equipmentSlot, BiConsumer<Holder<Attribute>, AttributeModifier> action) {
|
|
for (ItemAttributeModifiers.Entry entry : this.modifiers) {
|
|
if (entry.slot.test(equipmentSlot)) {
|
|
action.accept(entry.attribute, entry.modifier);
|
|
}
|
|
}
|
|
}
|
|
|
|
public double compute(double baseValue, EquipmentSlot equipmentSlot) {
|
|
double d = baseValue;
|
|
|
|
for (ItemAttributeModifiers.Entry entry : this.modifiers) {
|
|
if (entry.slot.test(equipmentSlot)) {
|
|
double e = entry.modifier.amount();
|
|
|
|
d += switch (entry.modifier.operation()) {
|
|
case ADD_VALUE -> e;
|
|
case ADD_MULTIPLIED_BASE -> e * baseValue;
|
|
case ADD_MULTIPLIED_TOTAL -> e * d;
|
|
};
|
|
}
|
|
}
|
|
|
|
return d;
|
|
}
|
|
|
|
public static class Builder {
|
|
private final ImmutableList.Builder<ItemAttributeModifiers.Entry> entries = ImmutableList.builder();
|
|
|
|
Builder() {
|
|
}
|
|
|
|
public ItemAttributeModifiers.Builder add(Holder<Attribute> attribute, AttributeModifier modifier, EquipmentSlotGroup slot) {
|
|
this.entries.add(new ItemAttributeModifiers.Entry(attribute, modifier, slot));
|
|
return this;
|
|
}
|
|
|
|
public ItemAttributeModifiers build() {
|
|
return new ItemAttributeModifiers(this.entries.build());
|
|
}
|
|
}
|
|
|
|
public record Entry(Holder<Attribute> attribute, AttributeModifier modifier, EquipmentSlotGroup slot) {
|
|
public static final Codec<ItemAttributeModifiers.Entry> CODEC = RecordCodecBuilder.create(
|
|
instance -> instance.group(
|
|
Attribute.CODEC.fieldOf("type").forGetter(ItemAttributeModifiers.Entry::attribute),
|
|
AttributeModifier.MAP_CODEC.forGetter(ItemAttributeModifiers.Entry::modifier),
|
|
EquipmentSlotGroup.CODEC.optionalFieldOf("slot", EquipmentSlotGroup.ANY).forGetter(ItemAttributeModifiers.Entry::slot)
|
|
)
|
|
.apply(instance, ItemAttributeModifiers.Entry::new)
|
|
);
|
|
public static final StreamCodec<RegistryFriendlyByteBuf, ItemAttributeModifiers.Entry> STREAM_CODEC = StreamCodec.composite(
|
|
Attribute.STREAM_CODEC,
|
|
ItemAttributeModifiers.Entry::attribute,
|
|
AttributeModifier.STREAM_CODEC,
|
|
ItemAttributeModifiers.Entry::modifier,
|
|
EquipmentSlotGroup.STREAM_CODEC,
|
|
ItemAttributeModifiers.Entry::slot,
|
|
ItemAttributeModifiers.Entry::new
|
|
);
|
|
|
|
public boolean matches(Holder<Attribute> attribute, ResourceLocation id) {
|
|
return attribute.equals(this.attribute) && this.modifier.is(id);
|
|
}
|
|
}
|
|
}
|