Solved PlayerInteractEntityEvent being applied twice.

Discussion in 'Plugin Development' started by PlonkerJim, Nov 25, 2020.

Thread Status:
Not open for further replies.
  1. So I am currently trying to make a plugin that spawns the user in with a compass and when right clicked it will point to the nearest player. I have made a function where when a player is right-clicked on with the compass they are added to a list so that they can be ignored and not tracked by the compass. When right-clicked again they are then removed from that list. It appears that whenever I click the player it runs this function twice so the player is added and then removed from the list. I understand I need to add some kind of bukkit scheduler however I am currently doing it wrong and as I am new to coding plugins I am a bit lost.

    Thanks for any help in advance,
    PlonkerJim

    Code:
    package org.plonkerjim.compasstest.tracker;
    
    import com.google.common.collect.Maps;
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.Comparator;
    import java.util.List;
    import java.util.Map;
    
    import org.bukkit.Bukkit;
    import org.bukkit.Material;
    import org.bukkit.entity.Player;
    import org.bukkit.event.EventHandler;
    import org.bukkit.event.Listener;
    import org.bukkit.event.block.Action;
    import org.bukkit.event.player.PlayerInteractEntityEvent;
    import org.bukkit.event.player.PlayerInteractEvent;
    import org.bukkit.event.player.PlayerMoveEvent;
    import org.plonkerjim.compasstest.Main;
    import org.plonkerjim.compasstest.packets.Packets;
    
    public class Tracker implements Listener {
      private Main plugin;
     
      private Map<Player, List<Player>> ignoredMap = Maps.newHashMap();
     
      public Tracker(Main plugin) {
        this.plugin = plugin;
      }
     
      @EventHandler
    public void onInteract(PlayerInteractEvent e) {
        Player p = e.getPlayer();
        if (this.plugin.isAutoTrackingMode())
          return;
        if ((e.getAction().equals(Action.RIGHT_CLICK_BLOCK) || e.getAction().equals(Action.RIGHT_CLICK_AIR)) &&
          e.getItem() != null && e.getItem().getType().equals(Material.COMPASS)) {
          Player tracked = track(p);
          if (tracked != null) {
            p.setCompassTarget(tracked.getLocation());
            if (this.plugin.isChatEnabled())
              p.sendMessage(this.plugin.getPrefix() + this.plugin.getMessageNearestPlayerTracked(tracked, (int)p.getLocation().distance(tracked.getLocation())));
          } else if (this.plugin.isChatEnabled()) {
            p.sendMessage(this.plugin.getPrefix() + this.plugin.getMessageNoPlayerFound());
          }
        }
      }
     
      @EventHandler
      public void onEntityInteract(PlayerInteractEntityEvent e) {
        Player p = e.getPlayer();
        Bukkit.getScheduler().runTaskLater(plugin, () -> {
            if (e.getRightClicked() instanceof Player)
                  if (p.getInventory().getItemInMainHand() != null && p.getInventory().getItemInMainHand().getType().equals(Material.COMPASS)) {
                    Player ignored = (Player)e.getRightClicked();
                    if (!this.ignoredMap.containsKey(p))
                      this.ignoredMap.put(p, new ArrayList<>());
                    List<Player> ignoredByPlayer = this.ignoredMap.get(p);
                    for(int i = 0; i < ignoredByPlayer.size(); i++) {
                        String thing = ignoredByPlayer.get(i).toString();
                        p.sendMessage(thing);
                    }
                    if (ignoredByPlayer.contains(ignored)) {
                      ignoredByPlayer.remove(ignored);
                      if (this.plugin.isChatEnabled())
                        p.sendMessage(this.plugin.getPrefix() + this.plugin.getMessagePlayerNoLongerIgnored(ignored));
                    } else {
                      ignoredByPlayer.add(ignored);
                      if (this.plugin.isChatEnabled())
                        p.sendMessage(this.plugin.getPrefix() + this.plugin.getMessagePlayerIsNowIgnored(ignored));
                    }
                  } 
        }, 20L);
      }
     
      @EventHandler
      public void onMove(PlayerMoveEvent e) {
        Player p = e.getPlayer();
        if (p.getInventory().getItemInOffHand() != null && p.getInventory().getItemInOffHand().getType().equals(Material.COMPASS) &&
          this.plugin.isAutoTrackingMode()) {
          Player t = track(p);
          if (t == null) {
            Packets.sendActionBar(p, this.plugin.getMessageNoPlayerFound());
          } else {
            p.setCompassTarget(t.getLocation());
            Packets.sendActionBar(p, this.plugin.getMessageNearestPlayerTracked(t, (int)p.getLocation().distance(t.getLocation())));
          }
        }
      }
     
      private Player track(Player tracking) {
        List<Player> players = new ArrayList<>();
        Player nearest = null;
        List<Player> ignored = this.ignoredMap.get(tracking);
        int trackingRange = this.plugin.getTrackingRange();
        for (Player p : tracking.getWorld().getEntitiesByClass(Player.class)) {
          if (!p.equals(tracking) &&
            !p.hasPermission(this.plugin.getIgnorePermission()) && (
            ignored == null || !ignored.contains(p)) && (
            trackingRange == -1 || tracking.getLocation().distance(p.getLocation()) <= trackingRange) &&
            tracking.canSee(p))
            players.add(p);
        }
        Collections.sort(players, new TrackerComperator(tracking));
        if (players.size() > 0)
          nearest = players.get(0);
        return nearest;
      }
     
      public class TrackerComperator implements Comparator<Player> {
        private Player player;
       
        public TrackerComperator(Player player) {
          this.player = player;
        }
       
        public int compare(Player o1, Player o2) {
          return compare(o1.getLocation().distance(this.player.getLocation()), o2.getLocation().distance(this.player.getLocation()));
        }
       
        private int compare(double a, double b) {
          return (a > b) ? -1 : ((a > b) ? 1 : 0);
        }
      }
    }
    Code:
    package org.plonkerjim.compasstest;
    
    import net.md_5.bungee.api.ChatColor;
    import org.bukkit.Bukkit;
    import org.bukkit.configuration.file.FileConfiguration;
    import org.bukkit.entity.Player;
    import org.bukkit.plugin.Plugin;
    import org.bukkit.plugin.java.JavaPlugin;
    import org.plonkerjim.compasstest.tracker.Tracker;
    
    public class Main extends JavaPlugin {
      private String ignorePermission;
     
      private String prefix;
     
      private String messageNoPlayerFound;
     
      private String messageNearestPlayerTracked;
     
      private String messagePlayerIsNowIgnored;
     
      private String messagePlayerIsNoLongerIgnored;
     
      private int trackingRange;
     
      private boolean chatEnabled;
     
      private boolean autoTrackingMode;
     
      public String getIgnorePermission() {
        return this.ignorePermission;
      }
     
      public String getPrefix() {
        return this.prefix;
      }
     
      public String getMessageNoPlayerFound() {
        return this.messageNoPlayerFound;
      }
     
      public String getMessageNearestPlayerTracked() {
        return this.messageNearestPlayerTracked;
      }
     
      public String getMessagePlayerIsNowIgnored() {
        return this.messagePlayerIsNowIgnored;
      }
     
      public String getMessagePlayerIsNoLongerIgnored() {
        return this.messagePlayerIsNoLongerIgnored;
      }
     
      public int getTrackingRange() {
        return this.trackingRange;
      }
     
      public boolean isChatEnabled() {
        return this.chatEnabled;
      }
     
      public boolean isAutoTrackingMode() {
        return this.autoTrackingMode;
      }
     
      public void onEnable() {
        init();
        Bukkit.getPluginManager().registerEvents(new Tracker(this), (Plugin)this);
      }
     
      private void init() {
        saveDefaultConfig();
        FileConfiguration cfg = getConfig();
        if (!cfg.isSet("auto-tracking-mode"))
          saveResource("config.yml", true);
        this.ignorePermission = "tracker.ignore";
        this.prefix = ChatColor.translateAlternateColorCodes('&', cfg.getString("message-prefix"));
        this.messageNoPlayerFound = ChatColor.translateAlternateColorCodes('&', cfg.getString("messages.no-player-found"));
        this.messageNearestPlayerTracked = ChatColor.translateAlternateColorCodes('&', cfg.getString("messages.player-tracked"));
        this.messagePlayerIsNoLongerIgnored = ChatColor.translateAlternateColorCodes('&', cfg.getString("messages.player-no-longer-ignored"));
        this.messagePlayerIsNowIgnored = ChatColor.translateAlternateColorCodes('&', cfg.getString("messages.player-ignored"));
        this.trackingRange = cfg.getInt("tracking-range");
        this.chatEnabled = cfg.getBoolean("enable-chat-messages");
        this.autoTrackingMode = cfg.getBoolean("auto-tracking-mode");
      }
     
      public String getMessageNearestPlayerTracked(Player tracked, int distance) {
        return this.messageNearestPlayerTracked.replaceAll("%p", tracked.getDisplayName()).replaceAll("%b", String.valueOf(distance));
      }
     
      public String getMessagePlayerNoLongerIgnored(Player ignored) {
        return this.messagePlayerIsNoLongerIgnored.replaceAll("%p", ignored.getDisplayName());
      }
     
      public String getMessagePlayerIsNowIgnored(Player ignored) {
        return this.messagePlayerIsNowIgnored.replaceAll("%p", ignored.getDisplayName());
      }
    }
    
    Code:
    package org.plonkerjim.compasstest.packets;
    
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.Method;
    import org.bukkit.Bukkit;
    import org.bukkit.entity.Player;
    
    public class Packets {
      private static final String VERSION;
     
      private static final boolean ACTION_BAR_SUPPORT;
     
      private static Field entityPlayer_playerConnection;
     
      private static Constructor<?> packetPlayOutChatConstructor;
     
      private static Constructor<?> chatMessageConstructor;
     
      private static Method craftPlayer_getHandle;
     
      private static Method playerConnection_sendPacket;
     
      static {
        String[] array = Bukkit.getServer().getClass().getPackage().getName().split("\\.");
        VERSION = (array.length == 4) ? (array[3] + ".") : "";
        boolean actionBarSupport = true;
        try {
          Class<?> packetPlayOutChat = getNMSClass("PacketPlayOutChat");
          packetPlayOutChatConstructor = packetPlayOutChat.getConstructor(new Class[] { getNMSClass("IChatBaseComponent"), byte.class });
          chatMessageConstructor = getNMSClass("ChatMessage").getConstructor(new Class[] { String.class, Object[].class });
          craftPlayer_getHandle = getCraftClass("entity.CraftPlayer").getMethod("getHandle", new Class[0]);
          entityPlayer_playerConnection = getNMSClass("EntityPlayer").getDeclaredField("playerConnection");
          playerConnection_sendPacket = getNMSClass("PlayerConnection").getMethod("sendPacket", new Class[] { getNMSClass("Packet") });
        } catch (ClassNotFoundException|NoSuchMethodException|NoSuchFieldException e) {
          e.printStackTrace();
          actionBarSupport = false;
        }
        ACTION_BAR_SUPPORT = actionBarSupport;
      }
     
      public static void sendActionBar(Player p, String message) {
        if (ACTION_BAR_SUPPORT)
          try {
            Object packet = packetPlayOutChatConstructor.newInstance(new Object[] { chatMessageConstructor.newInstance(new Object[] { message, new Object[0] }), Byte.valueOf((byte)2) });
            Object vanillaPlayer = craftPlayer_getHandle.invoke(p, new Object[0]);
            Object playerConnection = entityPlayer_playerConnection.get(vanillaPlayer);
            playerConnection_sendPacket.invoke(playerConnection, new Object[] { packet });
          } catch (IllegalAccessException|java.lang.reflect.InvocationTargetException|InstantiationException e) {
            e.printStackTrace();
          } 
      }
     
      public static Class<?> getCraftClass(String name) throws ClassNotFoundException {
        return Class.forName("org.bukkit.craftbukkit." + VERSION + name);
      }
     
      public static Class<?> getNMSClass(String name) throws ClassNotFoundException {
        return Class.forName("net.minecraft.server." + VERSION + name);
      }
    }
     
  2. Offline

    timtower Administrator Administrator Moderator

    @PlonkerJim You are not checking if it is the mainhand or offhand.
    It fires for both I believe.
     
  3. Code:
    @EventHandler
      public void onEntityInteract(PlayerInteractEntityEvent e) {
        Player p = e.getPlayer();
        Bukkit.getScheduler().runTaskLater(plugin, () -> {
            if (e.getRightClicked() instanceof Player)
                  if (p.getInventory().getItemInMainHand() != null && p.getInventory().getItemInMainHand().getType().equals(Material.COMPASS)) {
                    Player ignored = (Player)e.getRightClicked();
                    if (!this.ignoredMap.containsKey(p))
                      this.ignoredMap.put(p, new ArrayList<>());
                    List<Player> ignoredByPlayer = this.ignoredMap.get(p);
                    for(int i = 0; i < ignoredByPlayer.size(); i++) {
                        String thing = ignoredByPlayer.get(i).toString();
                        p.sendMessage(thing);
                    }
                    if (ignoredByPlayer.contains(ignored)) {
                      ignoredByPlayer.remove(ignored);
                      if (this.plugin.isChatEnabled())
                        p.sendMessage(this.plugin.getPrefix() + this.plugin.getMessagePlayerNoLongerIgnored(ignored));
                    } else {
                      ignoredByPlayer.add(ignored);
                      if (this.plugin.isChatEnabled())
                        p.sendMessage(this.plugin.getPrefix() + this.plugin.getMessagePlayerIsNowIgnored(ignored));
                    }
                  } 
        }, 20L);
      }
    This is the method that is getting applied twice, I am checking for ItemInMainHand()
     
  4. Offline

    timtower Administrator Administrator Moderator

  5. How can implement this into my code to fix my issue? I apologise I'm just very new to plugin coding :)
     
  6. Offline

    timtower Administrator Administrator Moderator

    @PlonkerJim You check it after the instanceof Player check
     
  7. Code:
    if (e.getRightClicked() instanceof Player && e.getHand() == (EquipmentSlot)HAND)
    Not quite sure how to implement the check but I was thinking something similar to this?

    Code:
            if (e.getRightClicked() instanceof Player && e.getHand() == EquipmentSlot.valueOf("HAND"))
    This is the fix ^^

    Thanks a bunch!!

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Nov 25, 2020
  8. Offline

    KarimAKL

    Use "EquipmentSlot.HAND" instead of "EquipmentSlot.valueOf("HAND")"
     
Thread Status:
Not open for further replies.

Share This Page