Added LastEntityDamagerTarget & LivingEntity#getLastDamageType

This commit is contained in:
Felix Cravic 2020-08-09 08:16:54 +02:00
parent dcf6bc2082
commit 7b5c6dfc44
5 changed files with 99 additions and 8 deletions

View File

@ -77,6 +77,7 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
protected UUID uuid;
private boolean isActive; // False if entity has only been instanced without being added somewhere
private boolean removed;
private boolean shouldRemove;
private long scheduledRemoveTime;
private EntityType entityType;
@ -1116,12 +1117,22 @@ public abstract class Entity implements Viewable, EventHandler, DataContainer {
* WARNING: this do not trigger the {@link EntityDeathEvent} event
*/
public void remove() {
this.removed = true;
this.shouldRemove = true;
entityById.remove(id);
if (instance != null)
instance.removeEntity(this);
}
/**
* Get if this entity has been removed
*
* @return true if this entity is removed
*/
public boolean isRemoved() {
return removed;
}
/**
* Trigger {@link #remove()} after the specified time
*

View File

@ -27,6 +27,7 @@ public abstract class LivingEntity extends Entity implements EquipmentHandler {
protected boolean isDead;
private float health;
private DamageType lastDamageType;
// Bounding box used for items' pickup (see LivingEntity#setBoundingBox)
protected BoundingBox expandedBoundingBox;
@ -244,7 +245,7 @@ public abstract class LivingEntity extends Entity implements EquipmentHandler {
// Additional hearts support
if (this instanceof Player) {
Player player = (Player) this;
final Player player = (Player) this;
final float additionalHearts = player.getAdditionalHearts();
if (additionalHearts > 0) {
if (damage > additionalHearts) {
@ -257,6 +258,7 @@ public abstract class LivingEntity extends Entity implements EquipmentHandler {
}
}
// Set the final entity health
setHealth(getHealth() - damage);
// play damage sound
@ -273,6 +275,9 @@ public abstract class LivingEntity extends Entity implements EquipmentHandler {
SoundEffectPacket damageSoundPacket = SoundEffectPacket.create(soundCategory, sound, getPosition().getX(), getPosition().getY(), getPosition().getZ(), 1.0f, 1.0f);
sendPacketToViewersAndSelf(damageSoundPacket);
}
// Set the last damage type since the event is not cancelled
this.lastDamageType = entityDamageEvent.getDamageType();
});
return !entityDamageEvent.isCancelled();
@ -312,6 +317,15 @@ public abstract class LivingEntity extends Entity implements EquipmentHandler {
sendMetadataIndex(8); // Health metadata index
}
/**
* Get the last damage type of this entity
*
* @return the last damage type, null if not any
*/
public DamageType getLastDamageType() {
return lastDamageType;
}
/**
* Get the entity max health from {@link #getAttributeValue(Attribute)} {@link Attribute#MAX_HEALTH}
*

View File

@ -3,10 +3,15 @@ package net.minestom.server.entity.ai.goal;
import net.minestom.server.entity.Entity;
import net.minestom.server.entity.EntityCreature;
import net.minestom.server.entity.ai.GoalSelector;
import net.minestom.server.entity.ai.TargetSelector;
import net.minestom.server.utils.Position;
import net.minestom.server.utils.time.CooldownUtils;
import net.minestom.server.utils.time.TimeUnit;
/**
* Attack the entity's target ({@link EntityCreature#getTarget()}) OR the closest entity
* which can be targeted with the entity {@link TargetSelector}
*/
public class MeleeAttackGoal extends GoalSelector {
private long lastHit;
@ -26,20 +31,21 @@ public class MeleeAttackGoal extends GoalSelector {
@Override
public boolean shouldStart() {
return entityCreature.getTarget() != null;
return getTarget() != null;
}
@Override
public void start() {
final Position targetPosition = entityCreature.getTarget().getPosition();
final Position targetPosition = getTarget().getPosition();
entityCreature.setPathTo(targetPosition);
}
@Override
public void tick(long time) {
final Entity target = entityCreature.getTarget();
final Entity target = getTarget();
if (target != null) {
// Attack the target entity
if (entityCreature.getBoundingBox().intersect(target)) {
if (!CooldownUtils.hasCooldown(time, lastHit, timeUnit, delay)) {
entityCreature.attack(target, true);
@ -48,6 +54,7 @@ public class MeleeAttackGoal extends GoalSelector {
return;
}
// Move toward the target entity
final Position pathPosition = entityCreature.getPathPosition();
final Position targetPosition = target.getPosition();
if (pathPosition == null || !pathPosition.isSimilar(targetPosition)) {
@ -63,6 +70,18 @@ public class MeleeAttackGoal extends GoalSelector {
@Override
public void end() {
// Stop following the target
entityCreature.setPathTo(null);
}
/**
* Use {@link EntityCreature#getTarget()} or
* the entity target selectors to get the correct target
*
* @return the target of the entity
*/
private Entity getTarget() {
final Entity target = entityCreature.getTarget();
return target == null ? findTarget() : target;
}
}

View File

@ -12,6 +12,9 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/**
* Target the closest entity
*/
public class ClosestEntityTarget extends TargetSelector {
private float range;
@ -37,11 +40,13 @@ public class ClosestEntityTarget extends TargetSelector {
for (Chunk chunk : chunks) {
final Set<Entity> entities = instance.getChunkEntities(chunk);
if (!(entities instanceof LivingEntity))
continue;
for (Entity ent : entities) {
// Only target living entities
if (!(ent instanceof LivingEntity)) {
continue;
}
// Don't target itself
if (ent.equals(entityCreature)) {
continue;
@ -56,12 +61,13 @@ public class ClosestEntityTarget extends TargetSelector {
break;
}
}
if (!correct) {
continue;
}
// Check distance
final float d = getEntityCreature().getDistance(ent);
final float d = entityCreature.getDistance(ent);
if ((entity == null || d < distance) && d < range) {
entity = ent;
distance = d;

View File

@ -0,0 +1,41 @@
package net.minestom.server.entity.ai.target;
import net.minestom.server.entity.Entity;
import net.minestom.server.entity.EntityCreature;
import net.minestom.server.entity.ai.TargetSelector;
import net.minestom.server.entity.damage.DamageType;
import net.minestom.server.entity.damage.EntityDamage;
/**
* Target the last damager of this entity
*/
public class LastEntityDamagerTarget extends TargetSelector {
private float range;
public LastEntityDamagerTarget(EntityCreature entityCreature, float range) {
super(entityCreature);
this.range = range;
}
@Override
public Entity findTarget() {
final DamageType damageType = entityCreature.getLastDamageType();
if (!(damageType instanceof EntityDamage)) {
// No damager recorded, return null
return null;
}
final EntityDamage entityDamage = (EntityDamage) damageType;
final Entity entity = entityDamage.getSource();
if (entity.isRemoved()) {
// Entity not valid
return null;
}
// Check range
return entityCreature.getDistance(entity) < range ? entity : null;
}
}