Solved Event handler for PlayerInteractEntityEvent running twice

Discussion in 'Spigot Plugin Development' started by Griffinator55, Jun 8, 2017.

  1. I am currently trying to create a plugin where something happens when the player clicks on a specific entitytype with a specific item. I am running into the issue where for almost every mob (excluding horse, Llama, and Villager) my event handler gets called twice when said mob is clicked on.

    Code (Text):

    @EventHandler
    public void onInteract(PlayerInteractEntityEvent event) {
        getLogger().info("Running PlayerInteractEntityEvent");
            if(canClick) {
                for(Clickable clickable : clickables) {
                    if(!clickable.compareEntities(event.getRightClicked()))
                        continue;
                    if(!clickable.compareItemClickedWith(event.getPlayer().getInventory().getItemInMainHand()))
                        continue;
                    clickable.giveItem(event.getPlayer());
                    break;
                }
            }
        }
     
     
  2. Try creating a cooldown of 1 tick
     
  3. That's a rather hackish way to deal with the problem. It does 'work', but the correct way to do it is to redesign the code to account for which hand is being used.

    @Griffinator55 The event fires twice because it must process the item in both the main-hand and the off-hand. That is where event.getHand() comes in. You can use getHand() to determine which item is actually being used on the entity instead of assuming getItemInMainHand() is the only option. If you really want the main-hand to be the only usable hand, just do a quick check for if(event.getHand()==EquipmentSlot.HAND)
     
  4. Oh, that makes sense, thank you for telling me that. quick question, I rewrote my code so that it checks based on the hand in the following manner. However, I was wondering if there was a way to simplify my rewritten code to get the Itemstack of the correct hand without having to separating it into two if statements. ie
    Code (Text):
    event.getPlayer.getInventory.getItem(event.getHand());
    instead of
    Code (Text):

    if (event.getHand().equals(EquipmentSlot.HAND)) {
                    if(!clickable.compareItemClickedWith(event.getPlayer().getInventory().getItemInMainHand()))
                            continue;
                  } else {
                     if(!clickable.compareItemClickedWith(event.getPlayer().getInventory().getItemInOffHand()))
                            continue;
    }
     
     
  5. Unfortunately, PlayerInteractEntityEvent does not have the convenient getItem() method like PlayerInteractEvent does. You'd have to write your own method to get the relative item based on the equipment slot.

    By the way, the EquipmentSlot class is an enum, so you should be using == instead of .equals(). Doing so makes your code shorter and you avoid potential NullPointerExceptions.