1.16.5 New Exhaustion Reason

Discussion in 'Spigot Plugin Development' started by TANG_N, Jun 14, 2021.

  1. I have searched the source code about EntityExhaustionEvent and ExhaustionReason.
    I want to add a new reason to it (For example shooting arrow will be an exhaustion event)
    but I'm kinda new to Java and not sure if I could just add a reason to it by creating a new Event that extends EntityExhaustionEvent and create a nested enum
    Code (Text):

    public class ShootingEvent extends EntityExhaustionEvent {
      ...

      public enum ExhaustionReason {

         ATTACK,

         SRPINT,

         (other original enum type),

         // The new enum
         SHOOTING
      }

    }
     
    Or do I have to do something to toggle the exhaustion event?


    btw is it possible to change the exhaustion level for some original event?
    For example something similar
    Code (Text):


    if(player.getInventory.getItemInMainHand() == something && player.isSprinting()) {
      player.setExhaustion(getExhaustion(SRPINT) + 0.1);
    }

     
     
  2. If you're new in Java and plugin in general, you should not try to create new event by yourself.

    The easiest way to use exhaustion event with other reason is to create another listener that will create an exhaustion event and call it. For example, when a player shoots an arrow (https://hub.spigotmc.org/javadocs/bukkit/org/bukkit/event/entity/EntityShootBowEvent.html), it's written manually and not tested :
    Code (Java):
    @EventHandler
    public void exhaustionWhenArrowShot(EntityShootBowEvent event) {
        if (event.getEntity() instanceof Player) {
            float exhaustionLvl = // something that depends on the force of the shoot or something
            EntityExhaustionEvent exhaustionEvent = new EntityExhaustionEvent(event.getEntity(), EntityExhaustionEvent.ExhaustionReason.UNKNOWN, exhaustionLvl);
            // call exhaustionEvent with callEvent method from pluginManager, look at javadoc
        }
    }
    If you want to use something like player.setExhaustion(getExhaustion(SPRINT) + 0.1);, you will have to do your own testing and get vanilla values, since a reason is not linked with a unique exhaust value.
     
  3. Thanks! It works!
    For sprinting one, how do I get the moment when player toggle sprint, something like this?
    Code (Text):

    @EventHandler
    public void exhaustionOnRunningWithBow(PlayerToggleSprintEvent e) {
      Player p = e.getPlayer();
      float exhaustion = p.getExhaustion();
      if(p.toggleSprint()) {
        Location oldLocation = p.getLocation();
      }
      if(!p.toggleSprint()) {
        Location newLocation = p.getLocation();
        float exhaustionValue = (float) (0.1F * oldLocation.distance(newLocation));
        EntityExhaustionEvent exhaustionEvent = new EntityExhaustionEvent(p, EntityExhaustionEvent.ExhaustionReason.SPRINT, exhaustionValue);
        pluginManager.callEvent(exhaustionEvent);
        p.setExhaustion(exhaustion + exhaustionValue);
      }
    }
     
    Or is there any life cycle for the event?
     
    #3 TANG_N, Jun 17, 2021
    Last edited: Jun 17, 2021
  4. Since EntityExhaustionEvent triggers while jumping or spriting, you can maybe listen to it directly, depending on what you want. I think your code is right.
     
  5. I tried the code but the distance is 0
    I'm not sure if I could use interface to transfer the status back and forth to this event handler (like transfering the oldLocation to Main and in the if(!e.isSprinting()), get the oldLocation from Main)
    Code (Text):

    @EventHandler
    public void exhaustionOnRunWithBow(PlayerToggleSprintEvent e) {
        Player p = e.getPlayer();
        float exhaustion = p.getExhaustion();
        float saturation = p.getSaturation();
        p.sendMessage(Utils.chat("Not called exhaustion, e = " + exhaustion + " s = " + saturation));
        Location oldLocation = p.getLocation(), newLocation;
        if (e.isSprinting()) {
            oldLocation = p.getLocation();
        }
        if (!e.isSprinting()) {
            newLocation = p.getLocation();
            double distance = oldLocation.distance(newLocation);
            float exhaustionValue = (float) (0.1F * distance);
            EntityExhaustionEvent exhaustionEvent = new EntityExhaustionEvent(p, EntityExhaustionEvent.ExhaustionReason.SPRINT, exhaustionValue);
            pluginManager.callEvent(exhaustionEvent);
            p.setExhaustion(exhaustion + exhaustionValue);
            exhaustion = p.getExhaustion();
            saturation = p.getSaturation();
            p.sendMessage(Utils.chat("Called exhaustion, e = " + exhaustion + " s = " + saturation));
            p.sendMessage(Utils.chat("Distance = " + distance));
        }
    }