Minestom/src/main/java/net/minestom/server/entity/attribute/AttributeInstance.java

139 lines
3.9 KiB
Java
Raw Normal View History

2024-04-10 06:34:30 +02:00
package net.minestom.server.entity.attribute;
2020-11-17 14:47:49 +01:00
2020-11-17 15:58:36 +01:00
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
2020-11-17 14:47:49 +01:00
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.function.Consumer;
2020-11-17 15:52:20 +01:00
/**
* Represents an instance of an attribute and its modifiers.
*/
public final class AttributeInstance {
2020-11-17 15:58:36 +01:00
private final Attribute attribute;
private final Map<UUID, AttributeModifier> modifiers = new HashMap<>();
private final Consumer<AttributeInstance> propertyChangeListener;
2024-04-10 06:34:30 +02:00
private double baseValue;
private double cachedValue = 0.0f;
2020-11-17 15:58:36 +01:00
public AttributeInstance(@NotNull Attribute attribute, @Nullable Consumer<AttributeInstance> listener) {
this.attribute = attribute;
this.propertyChangeListener = listener;
this.baseValue = attribute.defaultValue();
refreshCachedValue();
2020-11-17 15:58:36 +01:00
}
/**
* Gets the attribute associated to this instance.
*
* @return the associated attribute
*/
public @NotNull Attribute getAttribute() {
2020-11-17 15:58:36 +01:00
return attribute;
}
/**
* The base value of this instance without modifiers
*
* @return the instance base value
2024-04-10 06:34:30 +02:00
* @see #setBaseValue(double)
2020-11-17 15:58:36 +01:00
*/
2024-04-10 06:34:30 +02:00
public double getBaseValue() {
2020-11-17 15:58:36 +01:00
return baseValue;
}
/**
* Sets the base value of this instance.
*
* @param baseValue the new base value
* @see #getBaseValue()
*/
2024-04-10 06:34:30 +02:00
public void setBaseValue(double baseValue) {
2020-11-17 15:58:36 +01:00
if (this.baseValue != baseValue) {
this.baseValue = baseValue;
refreshCachedValue();
2020-11-17 15:58:36 +01:00
}
}
/**
* Add a modifier to this instance.
*
* @param modifier the modifier to add
*/
public void addModifier(@NotNull AttributeModifier modifier) {
if (modifiers.putIfAbsent(modifier.getId(), modifier) == null) {
refreshCachedValue();
2020-11-17 15:58:36 +01:00
}
}
/**
* Remove a modifier from this instance.
*
* @param modifier the modifier to remove
*/
public void removeModifier(@NotNull AttributeModifier modifier) {
removeModifier(modifier.getId());
}
/**
* Remove a modifier from this instance.
*
* @param uuid The UUID of the modifier to remove
*/
public void removeModifier(@NotNull UUID uuid) {
if (modifiers.remove(uuid) != null) {
refreshCachedValue();
2020-11-17 15:58:36 +01:00
}
}
/**
* Get the modifiers applied to this instance.
*
* @return the modifiers.
*/
@NotNull
2020-11-17 15:58:36 +01:00
public Collection<AttributeModifier> getModifiers() {
return modifiers.values();
}
/**
* Gets the value of this instance calculated with modifiers applied.
*
* @return the attribute value
*/
2024-04-10 06:34:30 +02:00
public double getValue() {
2020-11-17 15:58:36 +01:00
return cachedValue;
}
/**
* Recalculate the value of this attribute instance using the modifiers.
*/
private void refreshCachedValue() {
final Collection<AttributeModifier> modifiers = getModifiers();
2024-04-10 06:34:30 +02:00
double base = getBaseValue();
2020-11-17 15:58:36 +01:00
2024-04-12 17:00:16 +02:00
for (var modifier : modifiers.stream().filter(mod -> mod.getOperation() == AttributeOperation.ADD_VALUE).toArray(AttributeModifier[]::new)) {
2020-11-17 15:58:36 +01:00
base += modifier.getAmount();
}
2024-04-10 06:34:30 +02:00
double result = base;
2020-11-17 15:58:36 +01:00
for (var modifier : modifiers.stream().filter(mod -> mod.getOperation() == AttributeOperation.MULTIPLY_BASE).toArray(AttributeModifier[]::new)) {
2020-11-17 15:58:36 +01:00
result += (base * modifier.getAmount());
}
for (var modifier : modifiers.stream().filter(mod -> mod.getOperation() == AttributeOperation.MULTIPLY_TOTAL).toArray(AttributeModifier[]::new)) {
2020-11-17 15:58:36 +01:00
result *= (1.0f + modifier.getAmount());
}
this.cachedValue = Math.min(result, getAttribute().maxValue());
// Signal entity
if (propertyChangeListener != null) {
propertyChangeListener.accept(this);
}
2020-11-17 15:58:36 +01:00
}
2020-11-17 14:47:49 +01:00
}