Solved Player Interact with Custom NPC not working

Discussion in 'Spigot Plugin Development' started by CodeXPro, Jun 5, 2016.

  1. Hello, I am having a problem with PlayerInteractEntityEvent. It seems to trigger and work fine (Tested with debug messages) but doesn't trigger for any NPCs that I create with the NPC Handler class in the plugin.

    Here is how I am creating the npcs (3 methods):

    Code (Text):
    public static EntityPlayer getNPC(String name, String uuid) {
            MinecraftServer server = ((CraftServer) Bukkit.getServer()).getServer();
            WorldServer world = ((CraftWorld) Bukkit.getServer().getWorlds().get(0)).getHandle();
           
            return new EntityPlayer(server, world, new GameProfile(UUID.fromString(uuid), name), new PlayerInteractManager(world));
           
        }
    Code (Text):
    public static void createAllNPCS() {
           
            FileConfiguration config = Main.plugin.getConfig();
           
            List<String> allNpcs = config.getStringList("NPC.NPCList");
           
            for (String npcs : allNpcs) {
               
                Location npcLocation = new Location(Bukkit.getWorld(config.getString("NPC." + npcs + ".Location.World")), config.getInt("NPC." + npcs + ".Location.X"), config.getInt("NPC." + npcs + ".Location.Y"), config.getInt("NPC." + npcs + ".Location.Z"));
               
                EntityPlayer npc = getNPC(config.getString("NPC." + npcs + ".Name"), config.getString("NPC." + npcs + ".UUID"));
               
                npc.setLocation(npcLocation.getX(), npcLocation.getY(), npcLocation.getZ(), 0, 0);
               
                npcList.add(npc);
            }
        }
    Code (Text):

        public static void updateAllNPCPackets(Player p) {
            if (!(npcList.size() > 0)) return;
            for (EntityPlayer npcs : npcList) {
               
                PlayerConnection connection = ((CraftPlayer) p).getHandle().playerConnection;
                connection.sendPacket(new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.ADD_PLAYER, npcs));
                connection.sendPacket(new PacketPlayOutNamedEntitySpawn(npcs));
               
               
               
            }
           
        }

    Note that no errors are being thrown the event just doesn't trigger when I interact with these NPCs. The event triggers for all other entities that I have tested like mobs etc.

    Thanks for any help.
     
  2. PlayerInteractEntityEvent is not thrown when a players clicks a Fake Entity, listen to the PacketPlayInUseEntity instead, you can do it easily with ProtocolLib :)
     
    • Agree Agree x 1
  3. @MinusKube

    However I can do it with Citizens created NPCs, it triggers when I right click them.
     
  4. Citizens maybe use a system to call the event when the Fake NPC is clicked. Look at their sources if you want to know how they do it.
     
  5. @MinusKube
    Hmm I see, can you give me an example of how to do this using Protocol lib because I have never used it before.
     
  6. Code (Text):
    protocolManager.addPacketListener(new PacketAdapter(this, ListenerPriority.NORMAL, PacketType.Play.Client.USE_ENTITY){
                public void onPacketReceiving(PacketEvent e){
                    if(e.getPacketType() == PacketType.Play.Client.USE_ENTITY){
                        try {
                           
                             PacketContainer packet = e.getPacket();
                             Integer entId = packet.getIntegers().read(0);
                           
                             Player p = e.getPlayer();
                             
                             List<String> allNpcs = Main.plugin.getConfig().getStringList("NPC.NPCList");
                                 
                                 for (String s : allNpcs) {
                                     Integer id = getConfig().getInt("NPC." + s + ".ID");
                                     if (entId == id) {
                                         Bukkit.getServer().broadcastMessage("debug4");
                                         String command = Main.plugin.getConfig().getString("NPC." + s + ".Command").replaceAll("%player%", p.getName());
                                         
                                         Main.plugin.getServer().dispatchCommand(Main.plugin.getServer().getConsoleSender(), command);
                                         
                                     }
                                     
                                     
                                 }
                                 
                        } catch (Exception ex){}
                    }
                }
            });
    I am using protocol lib for this now, however when I read for integer 0 (Should be the ent ID) it returns a different ID then is returned by Bukkit for that entity. Basicly as a debug when I am creating the NPC I stored its ID in config, and usually it was something like 335 or 336. Then I am broadcasting the ID recieved from the Protocol Event yet they are completely different (68 is what I am getting from protocol). Quite confused as to why this is happening. Basicly I need to get the Entity from the USE_ENTITY event in protocol. The ID of the entity would be fine too but an actual Entity type return would be prefered. Any help is appreciated, thanks.
     
  7. @CodeXPro have you tried the PlayerInteractAtEntityEvent? If I recall correctly, that is fired for Players (in contrast with PlayerInteractEntityEvent)
     
  8. He's making a fake player so I believe this method won't work.
     
  9. @DarkSeraphim

    I'll give that event a try really quick.

    EDIT:

    That event doesn't trigger with fake players either. The thing is that the Protocol Event does trigger I just need to know how to get the entity that was interacted with.
     
  10. Bump, still need help with this.
     
  11. Code (Text):
    PacketPlayInUseEntity packet = new PacketPlayInUseEntity();
    Try saving the location of your spawned NPC and use the coordinates in the fields below.

    In addition, at the point of the location, get all of the entities in a nearby radius and check if they're interacting at the location of the NPC. I don't have any pseudo for you, but I'm sure that can help you conceptualize the process.

    [​IMG]
     
  12. Very helpful, thank you. I will give this a go and I will let you know how it goes.
     
  13. If you want to trigger an action if someone clicks an Npc, use an event. I recommend PlayerInteractEntityEvent.
     
  14. Already proved to not work with fake entities/players. @TunaFish
     
    • Like Like x 3
  15. @SwiftLee

    Okay so I am not sure on how to read for the coordinates of the interacted NPC.

    currently I am trying to do it like so:

    Code (Text):
    protocolManager = ProtocolLibrary.getProtocolManager();
           
            protocolManager.addPacketListener(new PacketAdapter(this, ListenerPriority.NORMAL, PacketType.Play.Client.USE_ENTITY){
                public void onPacketReceiving(PacketEvent e){
                    if(e.getPacketType() == PacketType.Play.Client.USE_ENTITY){
                        try {

                             Bukkit.getServer().broadcastMessage("debug1");
                             PacketContainer packet = e.getPacket();

                             Bukkit.getServer().broadcastMessage("debug2");
                             
                             for (Float f : packet.getFloat().getValues()) {
                                 Bukkit.getServer().broadcastMessage(f + "");
                             }
                             
                           
                             Player p = e.getPlayer();
                             
                        } catch (Exception ex){}
                    }
                }
            });
    However with some Debug messages it seems the code doesn't go into the for loop and just either stops there or goes past it. Not sure how to grab the coordinates as the resource you showed says "Optional Floats" not sure what that means and how to manipulate that.
     
  16. When you spawn in the entity save the coordinates safely. Most likely YML.
     
  17. @SwiftLee

    I already am doing that, however how do I check the location of the entity that was interacted with so then I can check if the location is the same as the NPC saved in config and then do what I need to do.
     
  18. You're going to have to send the packet for interacting with entities when PlayerInteractEvent is fired when clicking the NPC. Otherwise, it won't be addressed. Make sure the packet is sending as well. Try debugging and developing other solutions. :D