minecraft-src/net/minecraft/world/entity/ai/attributes/AttributeMap.java
2025-07-04 02:00:41 +03:00

156 lines
5.9 KiB
Java

package net.minecraft.world.entity.ai.attributes;
import com.google.common.collect.Multimap;
import com.mojang.logging.LogUtils;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import net.minecraft.Util;
import net.minecraft.core.Holder;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.resources.ResourceLocation;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
public class AttributeMap {
private static final Logger LOGGER = LogUtils.getLogger();
private final Map<Holder<Attribute>, AttributeInstance> attributes = new Object2ObjectOpenHashMap<>();
private final Set<AttributeInstance> attributesToSync = new ObjectOpenHashSet<>();
private final Set<AttributeInstance> attributesToUpdate = new ObjectOpenHashSet<>();
private final AttributeSupplier supplier;
public AttributeMap(AttributeSupplier supplier) {
this.supplier = supplier;
}
private void onAttributeModified(AttributeInstance instance) {
this.attributesToUpdate.add(instance);
if (instance.getAttribute().value().isClientSyncable()) {
this.attributesToSync.add(instance);
}
}
public Set<AttributeInstance> getAttributesToSync() {
return this.attributesToSync;
}
public Set<AttributeInstance> getAttributesToUpdate() {
return this.attributesToUpdate;
}
public Collection<AttributeInstance> getSyncableAttributes() {
return (Collection<AttributeInstance>)this.attributes
.values()
.stream()
.filter(attributeInstance -> attributeInstance.getAttribute().value().isClientSyncable())
.collect(Collectors.toList());
}
@Nullable
public AttributeInstance getInstance(Holder<Attribute> attribute) {
return (AttributeInstance)this.attributes.computeIfAbsent(attribute, holder -> this.supplier.createInstance(this::onAttributeModified, holder));
}
public boolean hasAttribute(Holder<Attribute> attribute) {
return this.attributes.get(attribute) != null || this.supplier.hasAttribute(attribute);
}
public boolean hasModifier(Holder<Attribute> attribute, ResourceLocation id) {
AttributeInstance attributeInstance = (AttributeInstance)this.attributes.get(attribute);
return attributeInstance != null ? attributeInstance.getModifier(id) != null : this.supplier.hasModifier(attribute, id);
}
public double getValue(Holder<Attribute> attribute) {
AttributeInstance attributeInstance = (AttributeInstance)this.attributes.get(attribute);
return attributeInstance != null ? attributeInstance.getValue() : this.supplier.getValue(attribute);
}
public double getBaseValue(Holder<Attribute> attribute) {
AttributeInstance attributeInstance = (AttributeInstance)this.attributes.get(attribute);
return attributeInstance != null ? attributeInstance.getBaseValue() : this.supplier.getBaseValue(attribute);
}
public double getModifierValue(Holder<Attribute> attribute, ResourceLocation id) {
AttributeInstance attributeInstance = (AttributeInstance)this.attributes.get(attribute);
return attributeInstance != null ? attributeInstance.getModifier(id).amount() : this.supplier.getModifierValue(attribute, id);
}
public void addTransientAttributeModifiers(Multimap<Holder<Attribute>, AttributeModifier> modifiers) {
modifiers.forEach((holder, attributeModifier) -> {
AttributeInstance attributeInstance = this.getInstance(holder);
if (attributeInstance != null) {
attributeInstance.removeModifier(attributeModifier.id());
attributeInstance.addTransientModifier(attributeModifier);
}
});
}
public void removeAttributeModifiers(Multimap<Holder<Attribute>, AttributeModifier> modifiers) {
modifiers.asMap().forEach((holder, collection) -> {
AttributeInstance attributeInstance = (AttributeInstance)this.attributes.get(holder);
if (attributeInstance != null) {
collection.forEach(attributeModifier -> attributeInstance.removeModifier(attributeModifier.id()));
}
});
}
public void assignAllValues(AttributeMap map) {
map.attributes.values().forEach(attributeInstance -> {
AttributeInstance attributeInstance2 = this.getInstance(attributeInstance.getAttribute());
if (attributeInstance2 != null) {
attributeInstance2.replaceFrom(attributeInstance);
}
});
}
public void assignBaseValues(AttributeMap map) {
map.attributes.values().forEach(attributeInstance -> {
AttributeInstance attributeInstance2 = this.getInstance(attributeInstance.getAttribute());
if (attributeInstance2 != null) {
attributeInstance2.setBaseValue(attributeInstance.getBaseValue());
}
});
}
public void assignPermanentModifiers(AttributeMap attributeMap) {
attributeMap.attributes.values().forEach(attributeInstance -> {
AttributeInstance attributeInstance2 = this.getInstance(attributeInstance.getAttribute());
if (attributeInstance2 != null) {
attributeInstance2.addPermanentModifiers(attributeInstance.getPermanentModifiers());
}
});
}
public ListTag save() {
ListTag listTag = new ListTag();
for (AttributeInstance attributeInstance : this.attributes.values()) {
listTag.add(attributeInstance.save());
}
return listTag;
}
public void load(ListTag nbt) {
for (int i = 0; i < nbt.size(); i++) {
CompoundTag compoundTag = nbt.getCompound(i);
String string = compoundTag.getString("id");
ResourceLocation resourceLocation = ResourceLocation.tryParse(string);
if (resourceLocation != null) {
Util.ifElse(BuiltInRegistries.ATTRIBUTE.get(resourceLocation), reference -> {
AttributeInstance attributeInstance = this.getInstance(reference);
if (attributeInstance != null) {
attributeInstance.load(compoundTag);
}
}, () -> LOGGER.warn("Ignoring unknown attribute '{}'", resourceLocation));
} else {
LOGGER.warn("Ignoring malformed attribute '{}'", string);
}
}
}
}