Solved NPCs disappearing when out of range

Discussion in 'Spigot Plugin Development' started by XlordalX, May 16, 2016.

Thread Status:
Not open for further replies.
  1. When the NPC's chunk unloads, the NPC seems to have disappeared when coming back. This does not happen if I do not remove the fake player from the tab list.

    NPC class:

    Code (Text):
    public class BountyNPC
    {
        private static final Property TEXTURE = new Property("textures", "eyJ0aW1lc3RhbXAiOjE0NjMzNDI0MTQ4MjIsInByb2ZpbGVJZCI6ImNiNjg0NTRmMjU0ZTQ5N" +
                "TU4MjAzNDJhN2JmOGRiZTIwIiwicHJvZmlsZU5hbWUiOiJNb29uR2xhcmUiLCJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQu" +
                "bmV0L3RleHR1cmUvMzIzMDIzOTIyYTk1YzVmNDExZjA2MTY2MjljZTg2ZWE5MmI4MjU5MjdlYjA1Njg5ZDcyNWUzYjM3ODM0MCJ9fX0=",
                "voVSnzljyYxYN1xvZZmkEShl47GH9GrIjiux51xUHWPB4CP3SqYXUFW6E8+gPg1HnWF1FvrJmgWc30Ob+rhiMri1TcTWvnOZ84g18sPABmh1fFh44BTO5cpdeizokj8YQvO" +
                        "OTZHQUTmaWoNkHwlvqOIVHG9iDRa0muc8D7FMNDYvuKu0gJmxq5VDidSar6lNWiiSjnwZokwqfkMQ9b8CdnM9VNi9M6pmA7JklKT7mPH5fP01hoDG/lC72ZkBc3" +
                        "DN/sD3ibQzAyPr4XimJwRCM3JEfsLj0HebA6FlmaoiiewXxh7eO0c9eo9ESTJQcr3DE2LM8P952nQIjn+Oom/+GtcNMFOKwlg4tg07aUM6EAYu3Jdl2Ioq0L9/y" +
                        "JiOcvikVA2pk6dg1oiFL+t8+lws0zqpEmvs+Ioip1XJIXlgUQOAvAHbpqsrBxIMFyWlrcIVTwUaLIqMRDt/6HA1UgXQhJSrUzhLPCwLrNI6EzIQJEQuPWYlTXi3" +
                        "nIi0kFvWqIM1k8XPIlfULif/eSh722ZIzuXyfdpBTpHGjv3ZFlVBiULhM0lUK8FAFhaki+WLJvpSI/RBPcpv8Q8DftbapEk/UKrDyeBnhhAGzPKSwNh9t2pfRtUA" +
                        "SMCGyDsXO55wSgNQKSHgaA2oHb+4plyqyqkH4nTMbi7WR0U4CJcvTA52pM8=");


        private ShadedBounties plugin;
        private Location location;
        private EntityPlayer npc;

        public BountyNPC(ShadedBounties plugin)
        {
            this.plugin = plugin;
            plugin.getNPCs().add(this);
        }

        public void spawn(Location location)
        {
            this.location = location;
            WorldServer world = NMSUtils.getNMSWorld(location.getWorld());
            GameProfile gameProfile = new GameProfile(UUID.fromString("259631f6-804d-4ce5-9e67-d47e236728d2"), "Bounty Hunter");

            gameProfile.getProperties().put("textures", TEXTURE);
            final EntityPlayer player = new EntityPlayer(NMSUtils.getNMSServer(Bukkit.getServer()), world,
                    gameProfile, new PlayerInteractManager(world));

            this.npc = player;
            player.playerConnection = new PlayerConnection(NMSUtils.getNMSServer(Bukkit.getServer()),
                    new NetworkManager(EnumProtocolDirection.SERVERBOUND), player);
            player.playerInteractManager.b(WorldSettings.EnumGamemode.CREATIVE);

            player.getBukkitEntity().setRemoveWhenFarAway(false);
            world.addEntity(player);
            player.setPositionRotation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());

            for(Player target : Bukkit.getOnlinePlayers())
            {
                sendPackets(target);
            }
        }

        public void sendPackets(Player bukkitPlayer)
        {
            final PlayerConnection playerConnection = NMSUtils.getNMSPlayer(bukkitPlayer).playerConnection;
            playerConnection.sendPacket(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, npc));
            playerConnection.sendPacket(new PacketPlayOutNamedEntitySpawn(npc));
            playerConnection.sendPacket(new PacketPlayOutEntityHeadRotation(npc, (byte)(location.getYaw() / 360 * 256)));

            new BukkitRunnable()
            {
                @Override
                public void run()
                {
                    playerConnection.sendPacket(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.REMOVE_PLAYER, npc));
                }
            }.runTaskLater(plugin, 3);
        }

        public EntityPlayer getPlayer()
        {
            return npc;
        }

        public Location getLocation()
        {
            return location;
        }
    How can I fix this without keeping the player on the tab list?
     
  2. Maybe cancel ChunkUnloadEvent?
     
  3. I tried that, but apperantly the chunks have nothing to do with it, it's just the range which despawns them.
     
  4. Set them as persistent entities (NBT tag).
    Non-animal entities tend to despawn if nobody is nearby for a period of time, this is what is happening, right?
     
  5. I have
    Code (Text):
    player.getBukkitEntity().setRemoveWhenFarAway(false);
    which does that.
     
  6. Ok, i think i may know what is happening..
    What exactly are you using for the entity? Is it a custom class, and are you properly resending the packets or modifying fields (if it is a custom NMS entity) on restart/reload?

    Check if the entity is truly gone, or simply invisible to players.
     
  7. It's not a custom entity, just a wrapper. I resend the packets on join.
     
  8. sothatsit

    Patron

    NPC's only appear for the client if they are in the tablist.
     
  9. This isn't entirely correct. An NPC will show for the client if you send the tab list add player packet, spawn the entity for the player and then send the tab list remove packet. However, if you don't send the remove packet, the NPC will persist properly on the client side. I could be wrong though, haven't tested that.
    EDIT: I didn't read the original post, OP wants to remove the NPC from tab. Other than perhaps running a scheduler that will respawn the entity if the player is too far away, I don't think you have any other options.
     
  10. sothatsit

    Patron

    They only appear if they are in the tablist. Never said they dissapeared when removed from the tablist. But yeah, that is right.
     
  11. Fixed by sending a player info add packet when the named entity spawn packet is sent.
     
    • Like Like x 1
    • Optimistic Optimistic x 1
Thread Status:
Not open for further replies.