mirror of
https://github.com/Minestom/Minestom.git
synced 2024-11-12 13:44:28 +01:00
Implement attribute instances
This commit is contained in:
parent
089f9a30aa
commit
d738f9fddd
@ -1,53 +1,69 @@
|
||||
package net.minestom.server.attribute;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public enum Attribute {
|
||||
public class Attribute {
|
||||
|
||||
MAX_HEALTH("generic.max_health", 20, 1024),
|
||||
FOLLOW_RANGE("generic.follow_range", 32, 2048),
|
||||
KNOCKBACK_RESISTANCE("generic.knockback_resistance", 0, 1),
|
||||
MOVEMENT_SPEED("generic.movement_speed", 0.25f, 1024),
|
||||
ATTACK_DAMAGE("generic.attack_damage", 2, 2048),
|
||||
ATTACK_SPEED("generic.attack_speed", 4, 1024),
|
||||
FLYING_SPEED("generic.flying_speed", 0.4f, 1024),
|
||||
ARMOR("generic.armor", 0, 30),
|
||||
ARMOR_TOUGHNESS("generic.armor_toughness", 0, 20),
|
||||
ATTACK_KNOCKBACK("generic.attack_knockback", 0, 5),
|
||||
LUCK("generic.luck", 0, 1024),
|
||||
HORSE_JUMP_STRENGTH("horse.jump_strength", 0.7f, 2),
|
||||
ZOMBIE_SPAWN_REINFORCEMENTS("zombie.spawn_reinforcements", 0, 1);
|
||||
private static final Map<String, Attribute> ATTRIBUTES = new HashMap<>();
|
||||
|
||||
private final String key;
|
||||
private final float defaultValue;
|
||||
private final float maxVanillaValue;
|
||||
private final String key;
|
||||
private final float defaultValue;
|
||||
private final float maxValue;
|
||||
private final boolean shareWithClient;
|
||||
|
||||
Attribute(@NotNull String key, float defaultValue, float maxVanillaValue) {
|
||||
this.key = key;
|
||||
this.defaultValue = defaultValue;
|
||||
this.maxVanillaValue = maxVanillaValue;
|
||||
}
|
||||
public Attribute(@NotNull String key, float defaultValue, float maxValue) {
|
||||
this(key, false, defaultValue, maxValue);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
public Attribute(@NotNull String key, boolean shareWithClient, float defaultValue, float maxValue) {
|
||||
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;
|
||||
}
|
||||
|
||||
public float getDefaultValue() {
|
||||
return defaultValue;
|
||||
}
|
||||
@NotNull
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public float getMaxVanillaValue() {
|
||||
return maxVanillaValue;
|
||||
}
|
||||
public float getDefaultValue() {
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Attribute fromKey(@NotNull String key) {
|
||||
for (Attribute attribute : values()) {
|
||||
if (attribute.getKey().equals(key))
|
||||
return attribute;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public float getMaxValue() {
|
||||
return maxValue;
|
||||
}
|
||||
|
||||
public boolean isShared() {
|
||||
return shareWithClient;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Attribute register() {
|
||||
ATTRIBUTES.put(key, this);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Attribute fromKey(@NotNull String key) {
|
||||
return ATTRIBUTES.get(key);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Attribute[] values() {
|
||||
return ATTRIBUTES.values().toArray(new Attribute[0]);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Attribute[] sharedAttributes() {
|
||||
return ATTRIBUTES.values().stream().filter(Attribute::isShared).toArray(Attribute[]::new);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,94 @@
|
||||
package net.minestom.server.attribute;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class AttributeInstance {
|
||||
|
||||
private final Attribute attribute;
|
||||
private final Map<UUID, AttributeModifier> modifiers = new HashMap<>();
|
||||
private final Consumer<AttributeInstance> propertyChangeListener;
|
||||
private float baseValue;
|
||||
private boolean dirty = true;
|
||||
private float cachedValue = 0.0f;
|
||||
|
||||
public AttributeInstance(@NotNull Attribute attribute, @Nullable Consumer<AttributeInstance> listener) {
|
||||
this.attribute = attribute;
|
||||
this.propertyChangeListener = listener;
|
||||
this.baseValue = attribute.getDefaultValue();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Attribute getAttribute() {
|
||||
return attribute;
|
||||
}
|
||||
|
||||
public float getBaseValue() {
|
||||
return baseValue;
|
||||
}
|
||||
|
||||
private void setDirty() {
|
||||
if (!dirty) {
|
||||
dirty = true;
|
||||
if (propertyChangeListener != null) {
|
||||
propertyChangeListener.accept(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setBaseValue(float baseValue) {
|
||||
if (this.baseValue != baseValue) {
|
||||
this.baseValue = baseValue;
|
||||
setDirty();
|
||||
}
|
||||
}
|
||||
|
||||
public void addModifier(@NotNull AttributeModifier modifier) {
|
||||
if (modifiers.putIfAbsent(modifier.getId(), modifier) == null) {
|
||||
setDirty();
|
||||
}
|
||||
}
|
||||
|
||||
public void removeModifier(@NotNull AttributeModifier modifier) {
|
||||
if (modifiers.remove(modifier.getId()) != null) {
|
||||
setDirty();
|
||||
}
|
||||
}
|
||||
|
||||
public Collection<AttributeModifier> getModifiers() {
|
||||
return modifiers.values();
|
||||
}
|
||||
|
||||
public float getValue() {
|
||||
if (dirty) {
|
||||
cachedValue = processModifiers();
|
||||
dirty = false;
|
||||
}
|
||||
return cachedValue;
|
||||
}
|
||||
|
||||
protected float processModifiers() {
|
||||
float base = getBaseValue();
|
||||
|
||||
for (var modifier : modifiers.values().stream().filter(mod -> mod.getOperation() == AttributeOperation.ADDITION).toArray(AttributeModifier[]::new)) {
|
||||
base += modifier.getAmount();
|
||||
}
|
||||
|
||||
float result = base;
|
||||
|
||||
for (var modifier : modifiers.values().stream().filter(mod -> mod.getOperation() == AttributeOperation.MULTIPLY_BASE).toArray(AttributeModifier[]::new)) {
|
||||
result += (base * modifier.getAmount());
|
||||
}
|
||||
for (var modifier : modifiers.values().stream().filter(mod -> mod.getOperation() == AttributeOperation.MULTIPLY_TOTAL).toArray(AttributeModifier[]::new)) {
|
||||
result *= (1.0f + modifier.getAmount());
|
||||
}
|
||||
|
||||
return Math.min(result, getAttribute().getMaxValue());
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
package net.minestom.server.attribute;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
import io.netty.util.internal.ThreadLocalRandom;
|
||||
import net.minestom.server.utils.UniqueIdUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class AttributeModifier {
|
||||
|
||||
private final float amount;
|
||||
private final String name;
|
||||
private final AttributeOperation operation;
|
||||
private final UUID id;
|
||||
|
||||
public AttributeModifier(@NotNull String name, float amount, @NotNull AttributeOperation operation) {
|
||||
this(UniqueIdUtils.createRandomUUID(ThreadLocalRandom.current()), name, amount, operation);
|
||||
}
|
||||
|
||||
public AttributeModifier(@NotNull UUID id, @NotNull String name, float amount, @NotNull AttributeOperation operation) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.amount = amount;
|
||||
this.operation = operation;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public UUID getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public float getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public AttributeOperation getOperation() {
|
||||
return operation;
|
||||
}
|
||||
}
|
18
src/main/java/net/minestom/server/attribute/Attributes.java
Normal file
18
src/main/java/net/minestom/server/attribute/Attributes.java
Normal file
@ -0,0 +1,18 @@
|
||||
package net.minestom.server.attribute;
|
||||
|
||||
public final class Attributes
|
||||
{
|
||||
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();
|
||||
}
|
@ -3,7 +3,7 @@ package net.minestom.server.entity;
|
||||
import com.extollit.gaming.ai.path.HydrazinePathFinder;
|
||||
import com.extollit.gaming.ai.path.model.IPath;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.attribute.Attribute;
|
||||
import net.minestom.server.attribute.Attributes;
|
||||
import net.minestom.server.entity.ai.GoalSelector;
|
||||
import net.minestom.server.entity.ai.TargetSelector;
|
||||
import net.minestom.server.entity.pathfinding.PFPathingEntity;
|
||||
@ -134,7 +134,7 @@ public abstract class EntityCreature extends LivingEntity {
|
||||
this.path = pathFinder.updatePathFor(pathingEntity);
|
||||
|
||||
if (path != null) {
|
||||
final float speed = getAttributeValue(Attribute.MOVEMENT_SPEED);
|
||||
final float speed = getAttributeValue(Attributes.MOVEMENT_SPEED);
|
||||
final Position targetPosition = pathingEntity.getTargetPosition();
|
||||
moveTowards(targetPosition, speed);
|
||||
} else {
|
||||
|
@ -1,6 +1,8 @@
|
||||
package net.minestom.server.entity;
|
||||
|
||||
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.entity.damage.DamageType;
|
||||
import net.minestom.server.event.entity.EntityDamageEvent;
|
||||
@ -26,9 +28,12 @@ import net.minestom.server.utils.validate.Check;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
//TODO: Default attributes registration (and limitation ?)
|
||||
public abstract class LivingEntity extends Entity implements EquipmentHandler {
|
||||
|
||||
// Item pickup
|
||||
@ -44,7 +49,7 @@ public abstract class LivingEntity extends Entity implements EquipmentHandler {
|
||||
// Bounding box used for items' pickup (see LivingEntity#setBoundingBox)
|
||||
protected BoundingBox expandedBoundingBox;
|
||||
|
||||
private final float[] attributeValues = new float[Attribute.values().length];
|
||||
private final Map<String, AttributeInstance> attributeModifiers = new HashMap<>(Attribute.values().length);
|
||||
|
||||
private boolean isHandActive;
|
||||
private boolean offHand;
|
||||
@ -369,41 +374,48 @@ public abstract class LivingEntity extends Entity implements EquipmentHandler {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the entity max health from {@link #getAttributeValue(Attribute)} {@link Attribute#MAX_HEALTH}.
|
||||
* Gets the entity max health from {@link #getAttributeValue(Attribute)} {@link Attributes#MAX_HEALTH}.
|
||||
*
|
||||
* @return the entity max health
|
||||
*/
|
||||
public float getMaxHealth() {
|
||||
return getAttributeValue(Attribute.MAX_HEALTH);
|
||||
return getAttributeValue(Attributes.MAX_HEALTH);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the heal of the entity as its max health.
|
||||
* <p>
|
||||
* Retrieved from {@link #getAttributeValue(Attribute)} with the attribute {@link Attribute#MAX_HEALTH}.
|
||||
* Retrieved from {@link #getAttributeValue(Attribute)} with the attribute {@link Attributes#MAX_HEALTH}.
|
||||
*/
|
||||
public void heal() {
|
||||
setHealth(getAttributeValue(Attribute.MAX_HEALTH));
|
||||
setHealth(getAttributeValue(Attributes.MAX_HEALTH));
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the specified attribute value to {@code value}.
|
||||
* Retrieves the attribute instance and its modifiers.
|
||||
*
|
||||
* @param attribute The attribute to change
|
||||
* @param value the new value of the attribute
|
||||
* @param attribute the attribute instance to get
|
||||
* @return the attribute instance
|
||||
*/
|
||||
public void setAttribute(@NotNull Attribute attribute, float value) {
|
||||
this.attributeValues[attribute.ordinal()] = value;
|
||||
@NotNull
|
||||
public AttributeInstance getAttribute(@NotNull Attribute attribute) {
|
||||
if (!attributeModifiers.containsKey(attribute.getKey())) {
|
||||
attributeModifiers.put(attribute.getKey(), new AttributeInstance(attribute, this::onAttributeChanged));
|
||||
}
|
||||
return attributeModifiers.get(attribute.getKey());
|
||||
}
|
||||
|
||||
protected void onAttributeChanged(@NotNull AttributeInstance instance) { }
|
||||
|
||||
/**
|
||||
* Retrieves the attribute value set by {@link #setAttribute(Attribute, float)}.
|
||||
* Retrieves the attribute value.
|
||||
*
|
||||
* @param attribute the attribute value to get
|
||||
* @return the attribute value
|
||||
*/
|
||||
public float getAttributeValue(@NotNull Attribute attribute) {
|
||||
return this.attributeValues[attribute.ordinal()];
|
||||
AttributeInstance instance = attributeModifiers.get(attribute.getKey());
|
||||
return (instance != null) ? instance.getValue() : attribute.getDefaultValue();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -488,15 +500,16 @@ public abstract class LivingEntity extends Entity implements EquipmentHandler {
|
||||
EntityPropertiesPacket propertiesPacket = new EntityPropertiesPacket();
|
||||
propertiesPacket.entityId = getEntityId();
|
||||
|
||||
final int length = Attribute.values().length;
|
||||
EntityPropertiesPacket.Property[] properties = new EntityPropertiesPacket.Property[length];
|
||||
for (int i = 0; i < length; i++) {
|
||||
AttributeInstance[] instances = attributeModifiers.values().stream()
|
||||
.filter(i -> i.getAttribute().isShared())
|
||||
.toArray(AttributeInstance[]::new);
|
||||
EntityPropertiesPacket.Property[] properties = new EntityPropertiesPacket.Property[instances.length];
|
||||
for (int i = 0; i < properties.length; ++i) {
|
||||
EntityPropertiesPacket.Property property = new EntityPropertiesPacket.Property();
|
||||
|
||||
final Attribute attribute = Attribute.values()[i];
|
||||
final float value = getAttributeValue(attribute);
|
||||
final float value = instances[i].getBaseValue();
|
||||
|
||||
property.attribute = attribute;
|
||||
property.attribute = instances[i].getAttribute();
|
||||
property.value = value;
|
||||
|
||||
properties[i] = property;
|
||||
@ -511,7 +524,7 @@ public abstract class LivingEntity extends Entity implements EquipmentHandler {
|
||||
*/
|
||||
private void setupAttributes() {
|
||||
for (Attribute attribute : Attribute.values()) {
|
||||
setAttribute(attribute, attribute.getDefaultValue());
|
||||
attributeModifiers.put(attribute.getKey(), new AttributeInstance(attribute, this::onAttributeChanged));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,8 @@ package net.minestom.server.entity;
|
||||
import net.minestom.server.MinecraftServer;
|
||||
import net.minestom.server.advancements.AdvancementTab;
|
||||
import net.minestom.server.attribute.Attribute;
|
||||
import net.minestom.server.attribute.AttributeInstance;
|
||||
import net.minestom.server.attribute.Attributes;
|
||||
import net.minestom.server.bossbar.BossBar;
|
||||
import net.minestom.server.chat.ChatParser;
|
||||
import net.minestom.server.chat.ColoredText;
|
||||
@ -288,7 +290,7 @@ public class Player extends LivingEntity implements CommandSender {
|
||||
|
||||
@Override
|
||||
public float getAttributeValue(@NotNull Attribute attribute) {
|
||||
if (attribute == Attribute.MOVEMENT_SPEED) {
|
||||
if (attribute == Attributes.MOVEMENT_SPEED) {
|
||||
return walkingSpeed;
|
||||
}
|
||||
return super.getAttributeValue(attribute);
|
||||
@ -1020,9 +1022,8 @@ public class Player extends LivingEntity implements CommandSender {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAttribute(@NotNull Attribute attribute, float value) {
|
||||
super.setAttribute(attribute, value);
|
||||
if (playerConnection != null)
|
||||
protected void onAttributeChanged(@NotNull final AttributeInstance instance) {
|
||||
if (instance.getAttribute().isShared() && playerConnection != null)
|
||||
playerConnection.sendPacket(getPropertiesPacket());
|
||||
}
|
||||
|
||||
|
@ -4,7 +4,7 @@ import com.extollit.gaming.ai.path.model.Gravitation;
|
||||
import com.extollit.gaming.ai.path.model.IPathingEntity;
|
||||
import com.extollit.gaming.ai.path.model.Passibility;
|
||||
import com.extollit.linalg.immutable.Vec3d;
|
||||
import net.minestom.server.attribute.Attribute;
|
||||
import net.minestom.server.attribute.Attributes;
|
||||
import net.minestom.server.entity.EntityCreature;
|
||||
import net.minestom.server.utils.Position;
|
||||
|
||||
@ -26,7 +26,7 @@ public class PFPathingEntity implements IPathingEntity {
|
||||
|
||||
public PFPathingEntity(EntityCreature entity) {
|
||||
this.entity = entity;
|
||||
this.searchRange = entity.getAttributeValue(Attribute.FOLLOW_RANGE);
|
||||
this.searchRange = entity.getAttributeValue(Attributes.FOLLOW_RANGE);
|
||||
}
|
||||
|
||||
public Position getTargetPosition() {
|
||||
@ -113,7 +113,7 @@ public class PFPathingEntity implements IPathingEntity {
|
||||
return new Capabilities() {
|
||||
@Override
|
||||
public float speed() {
|
||||
return entity.getAttributeValue(Attribute.MOVEMENT_SPEED);
|
||||
return entity.getAttributeValue(Attributes.MOVEMENT_SPEED);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,6 +1,10 @@
|
||||
package net.minestom.server.network.packet.server.play;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import net.minestom.server.attribute.Attribute;
|
||||
import net.minestom.server.attribute.AttributeInstance;
|
||||
import net.minestom.server.attribute.AttributeModifier;
|
||||
import net.minestom.server.network.packet.server.ServerPacket;
|
||||
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
|
||||
import net.minestom.server.utils.binary.BinaryWriter;
|
||||
@ -30,9 +34,14 @@ public class EntityPropertiesPacket implements ServerPacket {
|
||||
|
||||
public Attribute attribute;
|
||||
public double value;
|
||||
public AttributeInstance instance;
|
||||
|
||||
private void write(BinaryWriter writer) {
|
||||
float maxValue = attribute.getMaxVanillaValue();
|
||||
if (instance != null) {
|
||||
attribute = instance.getAttribute();
|
||||
value = instance.getBaseValue();
|
||||
}
|
||||
float maxValue = attribute.getMaxValue();
|
||||
|
||||
// Bypass vanilla limit client-side if needed (by sending the max value allowed)
|
||||
final double v = value > maxValue ? maxValue : value;
|
||||
@ -40,8 +49,16 @@ public class EntityPropertiesPacket implements ServerPacket {
|
||||
writer.writeSizedString(attribute.getKey());
|
||||
writer.writeDouble(v);
|
||||
|
||||
// TODO support for AttributeOperation
|
||||
writer.writeVarInt(0);
|
||||
{
|
||||
Collection<AttributeModifier> modifiers = instance.getModifiers();
|
||||
writer.writeVarInt(modifiers.size());
|
||||
|
||||
for (var modifier : modifiers) {
|
||||
writer.writeUuid(modifier.getId());
|
||||
writer.writeDouble(modifier.getAmount());
|
||||
writer.writeByte((byte) modifier.getOperation().getId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
package net.minestom.server.utils;
|
||||
|
||||
import java.util.Random;
|
||||
import java.util.UUID;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@ -20,4 +21,11 @@ public final class UniqueIdUtils {
|
||||
return input.matches(UNIQUE_ID_PATTERN.pattern());
|
||||
}
|
||||
|
||||
public static UUID createRandomUUID(Random random) {
|
||||
long most = random.nextLong() & -61441L | 16384L;
|
||||
long least = random.nextLong() & 4611686018427387903L | Long.MAX_VALUE;
|
||||
|
||||
return new UUID(most, least);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
package demo.entity;
|
||||
|
||||
import net.minestom.server.attribute.Attribute;
|
||||
import net.minestom.server.attribute.Attributes;
|
||||
import net.minestom.server.entity.LivingEntity;
|
||||
import net.minestom.server.entity.ai.goal.RandomStrollGoal;
|
||||
import net.minestom.server.entity.damage.DamageType;
|
||||
@ -37,7 +37,7 @@ public class ChickenCreature extends EntityChicken {
|
||||
//targetSelectors.add(new ClosestEntityTarget(this, 15, LivingEntity.class));
|
||||
|
||||
|
||||
setAttribute(Attribute.MOVEMENT_SPEED, 0.1f);
|
||||
getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(0.1f);
|
||||
|
||||
addEventCallback(EntityAttackEvent.class, event -> {
|
||||
//System.out.println("CALL ATTACK");
|
||||
|
Loading…
Reference in New Issue
Block a user