Solved EntityDamageEvent: Who shot that arrow?

Discussion in 'Spigot Plugin Help' started by CaffeineNYC, Jul 12, 2021.

  1. An arrow can be shot by a Player, a hostile mob, or a non-LivingEntity (e.g. an arrow trap).

    Suppose an arrow is fired and hits a LivingEntity, like a tamed wolf or a player. An EntityDamage event fires with a cause of DamageCause.PROJECTILE, and my EntityDamageListener begins to execute.

    Is there a way of figuring out whether the arrow came from a player, a hostile mob, or a non-LivingEntity?

    I was poking through EntityDamageEvent and I don't see anything that would let me distinguish where the arrow came from.
  2. Get the actual shot arrow, from that you can get the shooter, than you can check the instance of the shooter to see if it's from a LivingEntity
    • Agree Agree x 2
  3. I was thinking about that. I noticed that when I shoot an arrow at an Entity, I can catch the event using both EntityDamage and EntityDamageByEntity (which inherits from EntityDamage).

    I guess I don't really understand the mechanism very well. Do both the individual events "fire"? Or do listeners simply catch an event e along with all its parent events?
  4. EntityDamageByEntity is an extension of EntityDamageEvent, so if you listen EntityDamageEvent you will check all of them - EntityDamageEvent AND EntityDamageByEntity, but when you listen to EntityDamageByEntity you will only check those, so technically less checks
    • Winner Winner x 1
  5. Very nice explanation. Thank you so much!
  6. I went trawling through the EntityDamage event structure. Holy cow, that thing is huge. I found a path that seemed promising...


    but from there, I was expecting to see a Player, but ... gosh, it seemed circular. I know it can't be, but expanding object after object in the symbolic debugger, it seemed to never end. I feel like I'm going down a rabbit hole, so I'm probably missing something obvious.

    How do I get the shot arrow?
  7. Listen to EntityDamageByEntityEvent, then check if #getDamager is of type Arrow (using "instanceof"). If it is, then you can use #getShooter and check if it is of type Player (again, using "instanceof"). If it is, then do your thing.
  8. Ahhh. OK, I thought you were talking about EntityDamage. Makes sense.

    I should probably just describe what I'm trying to do.

    I'd like to write a plugin that protects tamed wolves from damage, but I'd like for it to be configurable by the user. The way I see it, most people would want to configure this in three ways (I'll use projectiles as an example, but this also includes attack and perhaps sweep attack):

    1. Arrow shot from the tamer.
    2. Arrow shot from other players.
    3. Arrow shot from hostile mobs.
    4. Arrow shot from non-LivingEntities.

    For example, I can see someone wanting to cancel damage from their own arrows, but not from skeleton's arrows. So I'd like all 4 cases to be configurable via config.yml.

    I don't really see a way of doing this using one listener. If I use EntityDamage, I don't have the ability to distinguish between the 4 cases. If I use EntityDamageByEntity, I lose the ability to detect cases 3 and 4.

    It seems like I really need to create listeners for both EntityDamage and EntityDamageByEntity to allow the user to configure each case individually.

    Is that a fair assessment?
  9. Uhm... No?
    What does it matter who shot the arrow?
    EntityDamageByEntityEvent listens to famage by an entity - the entity in question here is the arrow - doesn't matter who shot it, even a dropper for all I care.
    As I said: you listen to EntityDamageByEntityEvent, check if the damager (#getDamager) is an Arrow. If it is, then you get the shooter (#getShooter) and check the 4 conditions in THAT.