Solved PlayerInteractEvent triggering twice?

Discussion in 'Plugin Development' started by MightyOne, May 14, 2018.

  1. Offline

    MightyOne

    Hey experts out there,

    I got the feeling that PlayerInteractEvent triggers twice. Actually that only happens if no certain action is performed like placing a block or opening a chest.
    This is the code I have been testing with, it really couldn't be more simple:

    Code:
    import org.bukkit.Bukkit;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.player.PlayerInteractEvent;
    import org.bukkit.plugin.java.JavaPlugin;
    
    public class Plugin extends JavaPlugin implements Listener {
    
        @Override
        public void onEnable() {
            Bukkit.getPluginManager().registerEvents(this, this);
        }
    
        @Override
        public void onDisable() {}
    
        @EventHandler
        public void interact(PlayerInteractEvent e) {
            e.getPlayer().sendMessage(e.getAction().name());
        }
    }
    I tested it in 1.12.2 but I am sure that it already bothered me in other versions.
    Anyway, I am wondering that I could not find any other threads answering this question or so.

    Can any genius answer me why this happens and how I can stop it?
    I mean there are plenty work arounds, like keeping track of the time passed between the 2 events (0 ticks). But I would feel more comfortable if there was an actual solution.

    Thanls for any help,
    MightyOne
     
  2. @MightyOne
    The event fires twice because this runs for both of the player's hands.

    To force it to only run once, make sure the hand used (Event#getHand()) is the main hand.
     
    maved145 likes this.
  3. Offline

    MightyOne

    @Zombie_Striker oh man thanks a lot

    Do you know how i coul dget this to work for plugins from 1.8 - 1.12?
     
    Last edited: May 14, 2018
  4. @MightyOne
    The simplest fix for 1.8 would be to do the following:
    1. create a boolean. Set it to true. This represents if the event should continue.
    2. Create a try/catch block. Let the catch be an "Error|Exception" to be able to catch missing-call errors along with just plain exceptions. This is what will make it compatible with 1.8.
    3. Inside the try-block, set the boolean equal to if the hand is equal to the main hand. If it is on 1.8, this should fail safely and continue afterwards.
    4. Then, for checking if the hand is the off hand, just check if the boolean is true. This will only happen if it is on 1.8, in which case it will always be true, or if in 1.9-1.12 the event if for the mainhand.
    The 'propper' way to do this would have been to use a bit of reflection and a wrapper, where the reflection checks if the getHand method exists and the wrapper controls whether to run 1.8-designed code or 1.9+ code. However, this requires knowledge in reflection and more lines to complete.
     
  5. Offline

    MightyOne

    @Zombie_Striker
    Code:
    if(Bukkit.getVersion().contains("1.8");
    Is also a nice way to get things to work sometimes. I mean I will leave this try-catch you suggested around it that for any special case that I cant predict right now but idk I like it with the version check as well
     

Share This Page