In DamageEntityEvent listener, how exactly do I get:

  1. The entity that caused the damage
  2. The entity that got damaged

It’s confusing to me and hope someone can help out. Thanks!

Hi.
So the entity that was damaged is actually already in the event. You can get it by the following

Entity damaged = event.getTargetEntity();

As for the entity that caused the damage in the first place, they arnt stored in the event directly as this event can fire if a entity gets damaged by anything such as falling.

Instead you will need to find the attacker through the cause system. Easiest way to do this is like the following

public void onAttack(DamageEntityEvent event, @First Entity attacker){

This means that the event will only fire if a entity damaged another. However please note that the “attacker” maybe a arrow, in which you can easily find the shooter, however the shooter maybe a dispenser or the damaged entity (shot up in the sky and let gravity do the rest)

1 Like

A DamageSource is always at the root of the cause for DamageEntityEvent and AttackEntityEvent, it contains information about the damage. I suggest using it to find the attacker.

@Listener
public void onDamageEntity(DamageEntityEvent e, @Root EntityDamageSource d) {
	Entity victim = e.getTargetEntity();
	Entity attacker = d instanceof IndirectEntityDamageSource ? ((IndirectEntityDamageSource) d).getIndirectSource() : d.getSource();
}
1 Like

Thanks so much!

However please note that the “attacker” maybe a arrow

In this case, why can’t I do “@First Player attacker” instead? Is this because this would create the issue of storing the DAMAGED PLAYER inside “attacker” if, say, the cause is a dispenser arrow?

To answer your question, yes it may get confused. However as @Yeregorix pointed out the DamageSource is always first, meaning that you could use @Root instead of @First which will avoid the confusion. However do note that still of the damage is a arrow shot by a player it will not fire as the damage was not directly caused by a player.

Thank you. How can I obtain the EntityDamageSource of a DamageEntityEvent without using @Root or any other @ tag?

EDIT Maybe event.getCause().root()?

Your edit is correct.

Thank you. It seems that I get a NullPointerException on the line:

DamageSource dmgSrc = (DamageSource) event.getCause().root();

Am I doing something wrong?

How are you causing the damage event? Shooting yourself? Fall damage? Getting attacked? Etc?
There maybe damage events that dont have a root cause, I believe fall damage and falling out of the world doesn’t have a cause, there maybe others.

My question is why arnt you using @Root parameter?

Thank you. It’s a player being shot by another player with an arrow.

My reasoning is that I’m not writing the code directly inside the @Listener method. Rather, my code is inside a helper function that takes in the DamageEntityEvent as a parameter. This helper function is inside the @Listener.

EDIT How would I know if a @Root exists? It returns an Object, not an Optional.

Object root;
if(root == null){
    //No root found
}

When annotating an argument with @Root, this argument will never be null when the method is called by the event system. This annotation is a filter. The method will not be called if there is no root or the root is not of the right type. In case of a DamageEntityEvent, there is always a root and the root is always a DamageSource.