mirror of
https://github.com/Minestom/Minestom.git
synced 2024-12-26 11:07:53 +01:00
Remove the concept of non-shared attribute
This commit is contained in:
parent
eee5778cfe
commit
6aaf5aa0ce
@ -3,102 +3,34 @@ package net.minestom.server.attribute;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Represents a {@link net.minestom.server.entity.LivingEntity living entity} attribute.
|
||||
*/
|
||||
public class Attribute {
|
||||
public record Attribute(String key, float defaultValue, float maxValue) {
|
||||
private static final Map<String, Attribute> ATTRIBUTES = new ConcurrentHashMap<>();
|
||||
|
||||
private static final Map<String, Attribute> ATTRIBUTES = new HashMap<>();
|
||||
public static final Attribute MAX_HEALTH = (new Attribute("generic.max_health", 20, 1024)).register();
|
||||
public static final Attribute FOLLOW_RANGE = (new Attribute("generic.follow_range", 32, 2048)).register();
|
||||
public static final Attribute KNOCKBACK_RESISTANCE = (new Attribute("generic.knockback_resistance", 0, 1)).register();
|
||||
public static final Attribute MOVEMENT_SPEED = (new Attribute("generic.movement_speed", 0.25f, 1024)).register();
|
||||
public static final Attribute ATTACK_DAMAGE = (new Attribute("generic.attack_damage", 2, 2048)).register();
|
||||
public static final Attribute ATTACK_SPEED = (new Attribute("generic.attack_speed", 4, 1024)).register();
|
||||
public static final Attribute FLYING_SPEED = (new Attribute("generic.flying_speed", 0.4f, 1024)).register();
|
||||
public static final Attribute ARMOR = (new Attribute("generic.armor", 0, 30)).register();
|
||||
public static final Attribute ARMOR_TOUGHNESS = (new Attribute("generic.armor_toughness", 0, 20)).register();
|
||||
public static final Attribute ATTACK_KNOCKBACK = (new Attribute("generic.attack_knockback", 0, 5)).register();
|
||||
public static final Attribute LUCK = (new Attribute("generic.luck", 0, 1024)).register();
|
||||
public static final Attribute HORSE_JUMP_STRENGTH = (new Attribute("horse.jump_strength", 0.7f, 2)).register();
|
||||
public static final Attribute ZOMBIE_SPAWN_REINFORCEMENTS = (new Attribute("zombie.spawn_reinforcements", 0, 1)).register();
|
||||
|
||||
public static final Attribute MAX_HEALTH = (new Attribute("generic.max_health", true, 20, 1024)).register();
|
||||
public static final Attribute FOLLOW_RANGE = (new Attribute("generic.follow_range", true, 32, 2048)).register();
|
||||
public static final Attribute KNOCKBACK_RESISTANCE = (new Attribute("generic.knockback_resistance", true, 0, 1)).register();
|
||||
public static final Attribute MOVEMENT_SPEED = (new Attribute("generic.movement_speed", true, 0.25f, 1024)).register();
|
||||
public static final Attribute ATTACK_DAMAGE = (new Attribute("generic.attack_damage", true, 2, 2048)).register();
|
||||
public static final Attribute ATTACK_SPEED = (new Attribute("generic.attack_speed", true, 4, 1024)).register();
|
||||
public static final Attribute FLYING_SPEED = (new Attribute("generic.flying_speed", true, 0.4f, 1024)).register();
|
||||
public static final Attribute ARMOR = (new Attribute("generic.armor", true, 0, 30)).register();
|
||||
public static final Attribute ARMOR_TOUGHNESS = (new Attribute("generic.armor_toughness", true, 0, 20)).register();
|
||||
public static final Attribute ATTACK_KNOCKBACK = (new Attribute("generic.attack_knockback", true, 0, 5)).register();
|
||||
public static final Attribute LUCK = (new Attribute("generic.luck", true, 0, 1024)).register();
|
||||
public static final Attribute HORSE_JUMP_STRENGTH = (new Attribute("horse.jump_strength", true, 0.7f, 2)).register();
|
||||
public static final Attribute ZOMBIE_SPAWN_REINFORCEMENTS = (new Attribute("zombie.spawn_reinforcements", true, 0, 1)).register();
|
||||
|
||||
private final String key;
|
||||
private final float defaultValue;
|
||||
private final float maxValue;
|
||||
private final boolean shareWithClient;
|
||||
|
||||
/**
|
||||
* Create a new attribute with a given key and default.
|
||||
* <p>
|
||||
* By default, this attribute will be sent to the client.
|
||||
* </p>
|
||||
*
|
||||
* @param key the attribute registry key
|
||||
* @param defaultValue the default value
|
||||
* @param maxValue the maximum allowed value
|
||||
*/
|
||||
public Attribute(@NotNull String key, float defaultValue, float maxValue) {
|
||||
this(key, true, defaultValue, maxValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new attribute with a given key and default.
|
||||
*
|
||||
* @param key the attribute registry key
|
||||
* @param shareWithClient whether to send this attribute to the client
|
||||
* @param defaultValue the default value
|
||||
* @param maxValue the maximum allowed value
|
||||
*/
|
||||
public Attribute(@NotNull String key, boolean shareWithClient, float defaultValue, float maxValue) {
|
||||
public Attribute {
|
||||
if (defaultValue > maxValue) {
|
||||
throw new IllegalArgumentException("Default value cannot be greater than the maximum allowed");
|
||||
}
|
||||
this.key = key;
|
||||
this.shareWithClient = shareWithClient;
|
||||
this.defaultValue = defaultValue;
|
||||
this.maxValue = maxValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the attribute unique key.
|
||||
*
|
||||
* @return the attribute key
|
||||
*/
|
||||
@NotNull
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the attribute default value that should be applied.
|
||||
*
|
||||
* @return the attribute default value
|
||||
*/
|
||||
public float getDefaultValue() {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the maximum value applicable to an entity for this attribute.
|
||||
*
|
||||
* @return the maximum value of this attribute
|
||||
*/
|
||||
public float getMaxValue() {
|
||||
return maxValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets whether this attribute's instances should be sent to clients.
|
||||
*
|
||||
* @return if this attribute is to be shared
|
||||
*/
|
||||
public boolean isShared() {
|
||||
return shareWithClient;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -108,8 +40,7 @@ public class Attribute {
|
||||
* @see #fromKey(String)
|
||||
* @see #values()
|
||||
*/
|
||||
@NotNull
|
||||
public Attribute register() {
|
||||
public @NotNull Attribute register() {
|
||||
ATTRIBUTES.put(key, this);
|
||||
return this;
|
||||
}
|
||||
@ -120,8 +51,7 @@ public class Attribute {
|
||||
* @param key the key of the attribute
|
||||
* @return the attribute for the key or null if not any
|
||||
*/
|
||||
@Nullable
|
||||
public static Attribute fromKey(@NotNull String key) {
|
||||
public static @Nullable Attribute fromKey(@NotNull String key) {
|
||||
return ATTRIBUTES.get(key);
|
||||
}
|
||||
|
||||
@ -130,18 +60,7 @@ public class Attribute {
|
||||
*
|
||||
* @return an array containing all registered attributes
|
||||
*/
|
||||
@NotNull
|
||||
public static Attribute[] values() {
|
||||
return ATTRIBUTES.values().toArray(new Attribute[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves registered attributes that are shared with the client.
|
||||
*
|
||||
* @return an array containing registered, sharable attributes
|
||||
*/
|
||||
@NotNull
|
||||
public static Attribute[] sharedAttributes() {
|
||||
return ATTRIBUTES.values().stream().filter(Attribute::isShared).toArray(Attribute[]::new);
|
||||
public static @NotNull Collection<@NotNull Attribute> values() {
|
||||
return ATTRIBUTES.values();
|
||||
}
|
||||
}
|
||||
|
@ -12,8 +12,7 @@ import java.util.function.Consumer;
|
||||
/**
|
||||
* Represents an instance of an attribute and its modifiers.
|
||||
*/
|
||||
public class AttributeInstance {
|
||||
|
||||
public final class AttributeInstance {
|
||||
private final Attribute attribute;
|
||||
private final Map<UUID, AttributeModifier> modifiers = new HashMap<>();
|
||||
private final Consumer<AttributeInstance> propertyChangeListener;
|
||||
@ -23,7 +22,7 @@ public class AttributeInstance {
|
||||
public AttributeInstance(@NotNull Attribute attribute, @Nullable Consumer<AttributeInstance> listener) {
|
||||
this.attribute = attribute;
|
||||
this.propertyChangeListener = listener;
|
||||
this.baseValue = attribute.getDefaultValue();
|
||||
this.baseValue = attribute.defaultValue();
|
||||
refreshCachedValue();
|
||||
}
|
||||
|
||||
@ -32,8 +31,7 @@ public class AttributeInstance {
|
||||
*
|
||||
* @return the associated attribute
|
||||
*/
|
||||
@NotNull
|
||||
public Attribute getAttribute() {
|
||||
public @NotNull Attribute getAttribute() {
|
||||
return attribute;
|
||||
}
|
||||
|
||||
@ -104,7 +102,7 @@ public class AttributeInstance {
|
||||
/**
|
||||
* Recalculate the value of this attribute instance using the modifiers.
|
||||
*/
|
||||
protected void refreshCachedValue() {
|
||||
private void refreshCachedValue() {
|
||||
final Collection<AttributeModifier> modifiers = getModifiers();
|
||||
float base = getBaseValue();
|
||||
|
||||
@ -121,7 +119,7 @@ public class AttributeInstance {
|
||||
result *= (1.0f + modifier.getAmount());
|
||||
}
|
||||
|
||||
this.cachedValue = Math.min(result, getAttribute().getMaxValue());
|
||||
this.cachedValue = Math.min(result, getAttribute().maxValue());
|
||||
|
||||
// Signal entity
|
||||
if (propertyChangeListener != null) {
|
||||
|
@ -18,8 +18,7 @@ public enum AttributeOperation {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static AttributeOperation fromId(int id) {
|
||||
public static @Nullable AttributeOperation fromId(int id) {
|
||||
if (id >= 0 && id < VALUES.length) {
|
||||
return VALUES[id];
|
||||
}
|
||||
|
@ -1,32 +0,0 @@
|
||||
package net.minestom.server.attribute;
|
||||
|
||||
/**
|
||||
* The Minecraft, vanilla, standards attributes.
|
||||
*
|
||||
* @deprecated use the constants in {@link Attribute}
|
||||
*/
|
||||
@Deprecated
|
||||
public final class Attributes {
|
||||
|
||||
public static final Attribute MAX_HEALTH = Attribute.MAX_HEALTH;
|
||||
public static final Attribute FOLLOW_RANGE = Attribute.FOLLOW_RANGE;
|
||||
public static final Attribute KNOCKBACK_RESISTANCE = Attribute.KNOCKBACK_RESISTANCE;
|
||||
public static final Attribute MOVEMENT_SPEED = Attribute.MOVEMENT_SPEED;
|
||||
public static final Attribute ATTACK_DAMAGE = Attribute.ATTACK_DAMAGE;
|
||||
public static final Attribute ATTACK_SPEED = Attribute.ATTACK_SPEED;
|
||||
public static final Attribute FLYING_SPEED = Attribute.FLYING_SPEED;
|
||||
public static final Attribute ARMOR = Attribute.ARMOR;
|
||||
public static final Attribute ARMOR_TOUGHNESS = Attribute.ARMOR_TOUGHNESS;
|
||||
public static final Attribute ATTACK_KNOCKBACK = Attribute.ATTACK_KNOCKBACK;
|
||||
public static final Attribute LUCK = Attribute.LUCK;
|
||||
public static final Attribute HORSE_JUMP_STRENGTH = Attribute.HORSE_JUMP_STRENGTH;
|
||||
public static final Attribute ZOMBIE_SPAWN_REINFORCEMENTS = Attribute.ZOMBIE_SPAWN_REINFORCEMENTS;
|
||||
|
||||
private Attributes() throws IllegalAccessException {
|
||||
throw new IllegalAccessException("Cannot instantiate a static class");
|
||||
}
|
||||
|
||||
protected static void init() {
|
||||
// Empty, here to register all the vanilla attributes
|
||||
}
|
||||
}
|
@ -3,7 +3,6 @@ package net.minestom.server.entity;
|
||||
import net.kyori.adventure.sound.Sound.Source;
|
||||
import net.minestom.server.attribute.Attribute;
|
||||
import net.minestom.server.attribute.AttributeInstance;
|
||||
import net.minestom.server.attribute.Attributes;
|
||||
import net.minestom.server.collision.BoundingBox;
|
||||
import net.minestom.server.coordinate.Point;
|
||||
import net.minestom.server.coordinate.Vec;
|
||||
@ -35,7 +34,10 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.temporal.TemporalUnit;
|
||||
import java.util.*;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class LivingEntity extends Entity implements EquipmentHandler {
|
||||
@ -51,7 +53,7 @@ public class LivingEntity extends Entity implements EquipmentHandler {
|
||||
// Bounding box used for items' pickup (see LivingEntity#setBoundingBox)
|
||||
protected BoundingBox expandedBoundingBox;
|
||||
|
||||
private final Map<String, AttributeInstance> attributeModifiers = new ConcurrentHashMap<>(Attribute.values().length);
|
||||
private final Map<String, AttributeInstance> attributeModifiers = new ConcurrentHashMap<>();
|
||||
|
||||
// Abilities
|
||||
protected boolean invulnerable;
|
||||
@ -423,7 +425,7 @@ public class LivingEntity extends Entity implements EquipmentHandler {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the entity max health from {@link #getAttributeValue(Attribute)} {@link Attributes#MAX_HEALTH}.
|
||||
* Gets the entity max health from {@link #getAttributeValue(Attribute)} {@link Attribute#MAX_HEALTH}.
|
||||
*
|
||||
* @return the entity max health
|
||||
*/
|
||||
@ -434,7 +436,7 @@ public class LivingEntity extends Entity implements EquipmentHandler {
|
||||
/**
|
||||
* Sets the heal of the entity as its max health.
|
||||
* <p>
|
||||
* Retrieved from {@link #getAttributeValue(Attribute)} with the attribute {@link Attributes#MAX_HEALTH}.
|
||||
* Retrieved from {@link #getAttributeValue(Attribute)} with the attribute {@link Attribute#MAX_HEALTH}.
|
||||
*/
|
||||
public void heal() {
|
||||
setHealth(getAttributeValue(Attribute.MAX_HEALTH));
|
||||
@ -446,9 +448,8 @@ public class LivingEntity extends Entity implements EquipmentHandler {
|
||||
* @param attribute the attribute instance to get
|
||||
* @return the attribute instance
|
||||
*/
|
||||
@NotNull
|
||||
public AttributeInstance getAttribute(@NotNull Attribute attribute) {
|
||||
return attributeModifiers.computeIfAbsent(attribute.getKey(),
|
||||
public @NotNull AttributeInstance getAttribute(@NotNull Attribute attribute) {
|
||||
return attributeModifiers.computeIfAbsent(attribute.key(),
|
||||
s -> new AttributeInstance(attribute, this::onAttributeChanged));
|
||||
}
|
||||
|
||||
@ -458,19 +459,17 @@ public class LivingEntity extends Entity implements EquipmentHandler {
|
||||
* @param attributeInstance the modified attribute instance
|
||||
*/
|
||||
protected void onAttributeChanged(@NotNull AttributeInstance attributeInstance) {
|
||||
if (attributeInstance.getAttribute().isShared()) {
|
||||
boolean self = false;
|
||||
if (this instanceof Player player) {
|
||||
PlayerConnection playerConnection = player.playerConnection;
|
||||
// connection null during Player initialization (due to #super call)
|
||||
self = playerConnection != null && playerConnection.getConnectionState() == ConnectionState.PLAY;
|
||||
}
|
||||
EntityPropertiesPacket propertiesPacket = getPropertiesPacket(Collections.singleton(attributeInstance));
|
||||
if (self) {
|
||||
sendPacketToViewersAndSelf(propertiesPacket);
|
||||
} else {
|
||||
sendPacketToViewers(propertiesPacket);
|
||||
}
|
||||
boolean self = false;
|
||||
if (this instanceof Player player) {
|
||||
PlayerConnection playerConnection = player.playerConnection;
|
||||
// connection null during Player initialization (due to #super call)
|
||||
self = playerConnection != null && playerConnection.getConnectionState() == ConnectionState.PLAY;
|
||||
}
|
||||
EntityPropertiesPacket propertiesPacket = new EntityPropertiesPacket(getEntityId(), List.of(attributeInstance));
|
||||
if (self) {
|
||||
sendPacketToViewersAndSelf(propertiesPacket);
|
||||
} else {
|
||||
sendPacketToViewers(propertiesPacket);
|
||||
}
|
||||
}
|
||||
|
||||
@ -481,8 +480,8 @@ public class LivingEntity extends Entity implements EquipmentHandler {
|
||||
* @return the attribute value
|
||||
*/
|
||||
public float getAttributeValue(@NotNull Attribute attribute) {
|
||||
AttributeInstance instance = attributeModifiers.get(attribute.getKey());
|
||||
return (instance != null) ? instance.getValue() : attribute.getDefaultValue();
|
||||
AttributeInstance instance = attributeModifiers.get(attribute.key());
|
||||
return (instance != null) ? instance.getValue() : attribute.defaultValue();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -575,22 +574,8 @@ public class LivingEntity extends Entity implements EquipmentHandler {
|
||||
*
|
||||
* @return an {@link EntityPropertiesPacket} linked to this entity
|
||||
*/
|
||||
@NotNull
|
||||
protected EntityPropertiesPacket getPropertiesPacket() {
|
||||
return getPropertiesPacket(attributeModifiers.values());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an {@link EntityPropertiesPacket} for this entity with the specified attribute values.
|
||||
*
|
||||
* @param attributes the attributes to include in the packet
|
||||
* @return an {@link EntityPropertiesPacket} linked to this entity
|
||||
*/
|
||||
protected @NotNull EntityPropertiesPacket getPropertiesPacket(@NotNull Collection<AttributeInstance> attributes) {
|
||||
// Get all the attributes which should be sent to the client
|
||||
final List<AttributeInstance> properties = attributes.stream()
|
||||
.filter(i -> i.getAttribute().isShared()).toList();
|
||||
return new EntityPropertiesPacket(getEntityId(), properties);
|
||||
protected @NotNull EntityPropertiesPacket getPropertiesPacket() {
|
||||
return new EntityPropertiesPacket(getEntityId(), List.copyOf(attributeModifiers.values()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -128,7 +128,7 @@ public abstract class ItemMetaBuilder implements TagWritable {
|
||||
"UUID", NBT.IntArray(Utils.uuidToIntArray(itemAttribute.getUuid())),
|
||||
"Amount", NBT.Double(itemAttribute.getValue()),
|
||||
"Slot", NBT.String(itemAttribute.getSlot().name().toLowerCase()),
|
||||
"AttributeName", NBT.String(itemAttribute.getAttribute().getKey()),
|
||||
"AttributeName", NBT.String(itemAttribute.getAttribute().key()),
|
||||
"Operation", NBT.Int(itemAttribute.getOperation().getId()),
|
||||
"Name", NBT.String(itemAttribute.getInternalName()))))
|
||||
.toList()
|
||||
|
@ -39,7 +39,7 @@ public record EntityPropertiesPacket(int entityId, List<AttributeInstance> prope
|
||||
for (AttributeInstance instance : properties) {
|
||||
final Attribute attribute = instance.getAttribute();
|
||||
|
||||
writer.writeSizedString(attribute.getKey());
|
||||
writer.writeSizedString(attribute.key());
|
||||
writer.writeDouble(instance.getBaseValue());
|
||||
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user