Solved Will EntityDamageByEntityEvent be cancelled?

Discussion in 'Plugin Development' started by Acer_Mortem, May 17, 2014.

Thread Status:
Not open for further replies.
  1. Offline

    Acer_Mortem

    If you've had any experience with the EntityDamageByEntityEvent, you'll realize that it is called a whole lot when a player is standing next to a dangerous mob such as a Zombie (the event is called every tick that the player is near the Zombie). Now, this event is cancelled the majority of the time based on factors relating to Minecraft and Bukkit, resulting in hitting less often, as we see in the game (only x out of 20 hits will actually hit every second).

    My question is, how can I tell if the event will be cancelled before it actually is? I'm trying to send a message whenever the player is actually hit, and not the event is only called.

    Example:

    Code:
        public void playerLoseHealthEventFromEntities(final EntityDamageByEntityEvent e){
            if(e.isCancelled()) return;
            if(e.getDamager() instanceof Player) return;
            if(!(e.getEntity() instanceof Player)) return;
            final Player p = (Player) e.getEntity();
            p.sendMessage("you got hit! " + p.getHealth());
    ^ The above is called a bunch of times resulting in something looking like this in the players chatbox:
    Code:
    you got hit! 20
    you got hit! 17
    you got hit! 17
    you got hit! 17
    you got hit! 14
    you got hit! 14
    you got hit! 11
    you got hit! 11
    you got hit! 8
    you got hit! 8
    you got hit! 8
    How can I make it so that it would appear like this:
    Code:
    you got hit! 20
    you got hit! 17
    you got hit! 14
    you got hit! 11
    you got hit! 8
     
  2. Offline

    rfsantos1996

    ignoreCancelled = true

    And check if LivingEntity's noDamageTicks >= 10 (you will get hit after 10 ticks)
     
  3. Offline

    Acer_Mortem


    What do you mean by ignoreCancelled?
     
  4. Offline

    Wingzzz

    For an Event, you annotate the method that will handle the event that your Listener is listening for with @EventHandler. Although, the EventHandler annotation can actually be parameterized.

    Refer to the following picture (source) for the full list of paramaters for EventHandler and what they do:
    [​IMG]

    This means I can actually create my annotation three different ways.

    Firstly, I can simply go with a non-parameterized annotation with the defaults of 'priority = EventPiority.NORMAL' and 'ignoreCancelled = false'. This would look like:
    Code:java
    1. @EventHandler


    Secondly, we could instead choose to simply just set one of the states and leave the other default. The reason I mention this is to display the fact that these are optional and you can select which ones you want to set. This would look like:
    Code:java
    1.  
    2. @EventHandler(priority = EventPriority.NORMAL)
    3. public void onPlayerJoin(PlayerJoinEvent event) {
    4. // do something
    5. }
    6.  
    7. // or
    8.  
    9. @EventHandler(ignoreCancelled = true)
    10. public void onPlayerJoin(PlayerJoinEvent event) {
    11. // do something
    12. }


    Thirdly, we can decide to explicitly set the handler's state by supplying the EventHandler with two parameters (one of type EventPriority, and one of type boolean). This would look roughly (because it depends on what you choose) like:
    Code:java
    1. @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true)
    2. public void onPlayerJoin(PlayerJoinEvent event) {
    3. // do something
    4. }


    So now that we've gone over what we can do with the EventHandler's parameters (if you still need clarification on what they do or any other part of the Event API please refer to this wiki page)

    So what rfsantos1996 was referring to was the fact that you could possibly solve your problem by adding the parameter 'ignoreCancelled = true' to your EventHandler for the event you're listening for. Now, to note this isn't the only way to achieve this functionality, you could also insert:
    Code:java
    1. if(event.isCancelled()) {
    2. return;
    3. }


    At the top of the method handling the Event. Although, the overuse of this in methods was exactly why (correct me if I'm mistaken) Bukkit added the parameter of 'ignoreCancelled' to EventHandler.

    Now, forgive me if I went over material you already know- I'm basing my post off of the pretence that you don't know it and as well for any other developers who may view this thread that they may understand your problem and have adequate material/sources to find solutions to it, as well as other related problems/issues.

    Feel free to tahg me if you have any other issues you'd like my input on and good luck with this one!
     
  5. Offline

    Acer_Mortem



    First off, thank you for writing a very long and detailed reply. It's nice to know that we have some people willing to explain things in full. Second, now that you mentioned the ignoreCancelled parameter for the EventHandler, I can finally get rid of that check that I always used at the top of my methods =3


    Ultimately, your noDamageTicks check worked very well, and made it "feel" as if you were getting hit right on time, but I have to ask, why does this happen? Why is 10 the magic number, and not a more pronounced number like 0 or 20?
     
  6. Offline

    AoH_Ruthless

    Acer_Mortem
    I think that's just how often a zombie hits a player. Could be wrong though.
     
  7. Offline

    rfsantos1996

    I don't really know why, but this is the getMaxNoDamageTick() divided by 2... (and max no damage ticks = 20).

    The reason of a lot of events causing no damage is because Minecraft have a threshold for damage (or you would take damage every 0.1ms or things like that, that would be horrible for gameplay), so even if the event is triggered, at final it won't make any effect because before damaging the player, Bukkit checks the noDamageTicks (the number of ticks since the last damage, I belive)

    OBS: sorry for any english mistakes and probably bad syntax, I didn't slept yet so I don't know how to organize my idea lol
     
  8. Offline

    Acer_Mortem


    After doing some more testing, it seems as if the checking for NoDamageTick works if the player is moving, however no damage occurs at all if the player is, say, trapped against a wall, and therefor cannot move. At this point, the player doesn't take any damage at all.

    For future reference for other people having this problem:

    Make this your noDamageTicks check:

    Code:
            if(p.getNoDamageTicks() > 10) return;
    make it equal to or greater than 10 is slightly inaccurate, as Bukkit checks for MORE than half the maxDamageTicks, not equal to or more.

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 8, 2016
Thread Status:
Not open for further replies.

Share This Page