[NMS] Player Entities and General NPCs

Discussion in 'Plugin Development' started by TheDummy, Jan 31, 2014.

Thread Status:
Not open for further replies.
  1. Offline

    TheDummy

    CaptainBern xTrollxDudex Garris0n

    I've used the setItemInHand(), but it doesn't change it. Here's the code:
    Code:java
    1. ((EntityHuman) p).getBukkitEntity().setItemInHand(
    2. new org.bukkit.inventory.ItemStack(
    3. Material.BEDROCK ) );


    Any of you have any ideas on how to make the player "jump" ?
     
  2. Offline

    Garris0n

    setVelocity()? As for the item, that should work...any errors?
     
  3. Offline

    TheDummy

    garris0n No errors in the terminal.

    Garris0n I edited out a few lines to trim anything that might be causing a conflict. The result was that I spawned into the server, damaged the entity (right clicked) to cause the item in hand change, and logged out.

    One of the lines I removed was the despawn on player exit and I returned to see the old entity holding the item in their hand. I suspect I need to send the players an "update" packet. Any ideas?

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 6, 2016
  4. Offline

    xTrollxDudex

  5. Offline

    TheDummy

    I tried chunk.unload() and then chunk.load() , but the NPC did not change.

    I can theoretically broadcast a PackerPlayOutEntityEquipment packet, but that's just a workaround. Shouldn't the built in methods do this automatically?
     
  6. Offline

    Garris0n

    Probably has something to do with the fact that you're deleting the system that handles their packets.
     
  7. Offline

    Jogy34

    Just for reference this is one of my custom NPC's setArmour() method which works completely fine for me:
    Code:java
    1.  
    2. public void setArmour(int slot, ItemStack stack)
    3. {
    4. if(slot < 0 || slot > 4) return;
    5. if(stack == null) stack = new ItemStack(Material.AIR);
    6. switch(slot)
    7. {
    8. case 0:
    9. this.inventory.items[0] = CraftItemStack.asNMSCopy(stack);
    10. this.inventory.itemInHandIndex = 0;
    11. this.carried = stack;
    12. break;
    13. case 1:
    14. this.inventory.armor[0] = CraftItemStack.asNMSCopy(stack);
    15. this.feet = stack;
    16. break;
    17. case 2:
    18. this.inventory.armor[1] = CraftItemStack.asNMSCopy(stack);
    19. this.legs = stack;
    20. break;
    21. case 3:
    22. this.inventory.armor[2] = CraftItemStack.asNMSCopy(stack);
    23. this.chest = stack;
    24. break;
    25. case 4:
    26. this.inventory.armor[3] = CraftItemStack.asNMSCopy(stack);
    27. this.head = stack;
    28. break;
    29. }
    30. ((WorldServer)this.world).getTracker().a(this, new PacketPlayOutEntityEquipment(this.getId(), slot, CraftItemStack.asNMSCopy(stack)));
    31. }
     
    Garris0n likes this.
  8. Offline

    TheDummy

    Garris0n I believe that system handles the clientbound packets such as damage and such. So by "deleting it," I tell the server you can't send the fake player any information. However, that shouldn't affect other players from seeing what I have changed on the fake player.

    Jogy34
    Code:java
    1. ((WorldServer)this.world)
    2. .getTracker()
    3. .a(this, new PacketPlayOutEntityEquipment(
    4. this.getId(), slot, CraftItemStack.asNMSCopy(stack)));

    I believe that should do it. You are broadcasting the player equip packet to the server, so players "see" the change. Thank you. I'll repost if there are problem with this.
     
  9. Offline

    Garris0n

    TheDummy I'm just assuming that, since it's the only thing being changed, that would be the source of the issue. Normally the packets would be broadcasted accordingly, but, for whatever reason, here you have to do it manually.
     
  10. Offline

    TheDummy

    Garris0n It IS very strange. I've been looking through the Entity class (particularly the move() method), but it doesn't seem to call any broadcast function yet everyone can see the movement. ... Very strange.
     
  11. Offline

    xTrollxDudex

    TheDummy
    Try npc.getBukkitEntity().getLocation().getChunk().unload(true, false)

    What you are doing is removing the NPC's PlayerConnection methods, but that's not what handles the movement. The movement protocol is sent to the players that see the movement, not the players that move.
     
  12. Offline

    TheDummy

    I see... but aren't broadcast packets supposed to be send to players so they see the movement? How does that happen if the move function doesn't call any packet broadcast functions? (Btw, I agree that the NullPlayerConnection does not handle movement)

    xTrollxDudex I've got it to work by broadcasting a packet using the tracker in WorldServer instance thanks to Jogy.

    Jogy34 It works. I just tested it out. The world's entity tracker calls a broadcast function that sends the item in hand update packet. Thank you so much.
     
  13. Offline

    xTrollxDudex

  14. Offline

    TheDummy

    xTrollxDudex That was my bad. I updated it late. Do you have any thoughts on pathfinding? Or at least making the entity jump?
     
  15. Offline

    xTrollxDudex

    TheDummy
    Not on pathing, but I found the answer to the movement. Just look for classes with PacketPlayOutRelEntityMove and that gets you towards EntityTrackerEntry. That is used in EntityTracker, which is used in WorldServer on startup. EntityTracker is probably updated each tick to send the move packets to each player.
     
  16. Offline

    TheDummy

    For anyone following this thread, I found a decent theoretical path finding solution in TopHat's NpcLib.

    Here's the address for the GitHub: https://github.com/Top-Cat/NPCLib

    I'll try to implement the path finding like this later, but for now I'll probably stick to teleports / using move().

    On a side note, does anyone know how to make the entity jump?

    CaptainBern xTrollxDudex Garris0n Jogy34
    I've hit a bit of a road block when trying to hide the entity from all but one player. The built in "setInvisible( boolean )" method makes it so the player is hidden from all players even if a named entity spawn packet or entity destroy packet is sent.
    I've tried sending Metadata packets containing "invisible" to all players when they join and send a "normal" Metadata packet when they interact with something (to make the entity visible again). Nothing seems to work and I'm all out of ideas.

    Edit: Sending a destroy entity packet on PlayerJoinEvent doesn't work, but it does on PlayerInteractEvent. Any explanations why the code below works in one event and not the other?
    Code:java
    1. ((CraftPlayer) event.getPlayer()).getHandle().playerConnection.sendPacket(
    2. new PacketPlayOutEntityDestroy( new int[] { playerNPC.getId() } ) );


    Edit: I just tried the entity metadata method. It also works in PlayerInteractEvent, but not in PlayerJoinEvent. What could be causing it to work on one event and not the other?

    Side question: In the PacketPlayOutEntityMetadata, there is a boolean as the third parameter. One leads to datawatcher.b() and the other goes to datawatcher.c() . Do any of you know what the difference is? The metadata method worked when setting that boolean to true, but not when the boolean was false.

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 6, 2016
  17. TheDummy send the packet 1 tick after the player joined.
     
  18. Offline

    Garris0n

    CaptainBern

    Also, perhaps you can use hidePlayer and showPlayer.
     
  19. Offline

    TheDummy

    CaptainBern I had the same idea and I tried with a 1 tick delay, but nothing happened. So I thought to myself, maybe the packet is being sent too early (before the player can "see" the world). So I set the tick delay to 20 seconds and it worked! (After some experimentation, 2 ticks also seems to work). Thanks, Captain.

    Garris0n Aren't those functions specific to Bukkit? Nonetheless, I appreciate the time you took to suggest it.

    CaptainBern Comphenix Jogy34 xTrollxDudex Garris0n
    Do you guys know of any way to set a display name of an entity, but retain the actual name for skins? I'd like the NPC to have my skin, but have a different display name. I can't seem to find a secondary String name variable in Entity / EntityHuman / EntityPlayer that would allow me to set a "display name."

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 6, 2016
    CaptainBern likes this.
  20. Offline

    Garris0n

    You can't, it's just how Minecraft handles skins. It downloads the skin based on the name of the player.
     
  21. Offline

    xTrollxDudex

    TheDummy
    Skins are client sided by the way.
     
  22. Offline

    TheDummy

    That's sucks. Thanks for letting me know.

    Oh is that why there are mods that can make it look like you have a skin if you don't?

    New related question at entities: I'm messing with PacketPlayOutEntityMetadata, but I can't make it spawn potion particles around the player. I've posted the code below. What am I doing wrong?
    Code:java
    1. DataWatcher effectData = new DataWatcher( null );
    2. effectData.a( 7 , new Integer( color ) );
    3. effectData.a( 8 , new Byte( (byte) 1 ) );
    4.  
    5. // I have no idea why the last boolean is true. I just put it there.
    6. PacketPlayOutEntityMetadata effectPacket = new PacketPlayOutEntityMetadata(
    7. entityID , effectData , true );


    Edit: My some stroke of luck, I edited out the 3rd line with the 8th index. Potion particles are spawning now. So, I submit a change to the question: What the heck does the 8th index do? The protocol site, Wiki.vg , says "is potion effect ambient." I assumed that meant "should the effect be shown?"
     
  23. Offline

    xTrollxDudex

    TheDummy
    I remember hearing that ambience has something to do with beacons?
     
  24. xTrollxDudex TheDummy Garris0n For the displayname, there's also the scoreboard apu, which, if I'm correct, allows one to change the displayname while keeping the skin. I have no idea how to do this tho.
     
  25. Offline

    Garris0n

    You can prefix it and suffix it.
     
    CaptainBern likes this.
  26. Offline

    TheDummy

    Garris0n CaptainBern Can you give me a link to where I can read up on the prefix / suffix system? Maybe the NMS class even?
     
  27. Offline

    Garris0n

    First read the scoreboard tutorial in resources. Then go poke around in mc-dev or craftbukkit (I'm not sure if cb has all the classes).
     
  28. Offline

    TheDummy

    I will be sure to do that.

    CaptainBern xTrollxDudex Garris0n Jogy34
    How do you guys set the datawatcher? Using the a() or watch() ? I was messing around with it and it seems like a() is like the "add" method and watch() is the "update" method. Is that correct?
     
  29. Offline

    TheDummy

    CaptainBern xTrollxDudex Garris0n Jogy34
    Sorry for the bother again, but my NPC doesn't seem to be affected by gravity (when I call move() on an arbitrary position). Is there a way to fix that?
    Edit: Ground collisions are okay, but if the player is told to move in the air, then there is "no gravity."
     
  30. TheDummy You will have to take care of the gravity yourself then. Make sure the npc isn't flying etc.
     
Thread Status:
Not open for further replies.

Share This Page