Packets? NPC's? ProtocolLib?

Discussion in 'Plugin Development' started by Someone_Like_You, Jan 17, 2014.

Thread Status:
Not open for further replies.
  1. Ive programming my own server, but at the moment Im kind of "stuck", I want to make it really looks good, however I have to use packets to create NPC for shops, my question are -
    1. How would I create an NPC with packets?
    2. How would I detect interaction with the NPC?
    3. How easy is it with ProtocolLib and w/o? (I would like to not depend on other libs or plugins.)
    4. Any good tutorial about learning and understanding packets and NMS?..
    5. After creating packet, you have to send it to players... so - would I have to send it to every player that login?
    *Please note: I would like to get some code, but more important than that - I would like explanation of how those stuff work (the code for example) since I really want to learn and less copy code...
     
  2. Offline

    Garris0n

    For the NPC questions, I think there are libs in resources.

    As for question #4, the best way to learn how to use NMS is to 1. know java and 2. look through this.
    There's also this info post by xTrollxDudex that is helpful.
     
    xTrollxDudex likes this.
  3. Garris0n I did look at xTrollxDudex tutorial , its helped me a lot, but I still cant understand few stuff...
    And for the NPC, I would like to code that NPC (not using lib, 1. Would help me learn, 2. I don't want to depend on other libs or plugins) , another question - how do I get packet that sent from client to sever? (NPC interact for example) , and thanks a lot for answer about the NMS stuff ;)
     
  4. I created a Library to do the very thing you're looking for. I'd advise you look through the code, though I haven't updated it to 1.7. http://forums.bukkit.org/threads/lib-spawning-basic-npcs.182928/

    To get it working, you would need to update to the latest packets (found here http://forums.bukkit.org/threads/info-1-7-x-protocol-changes-find-the-new-packet-names-here.201574/), and you'd need to use Reflection to get the values.

    As for interacting with them, CaptainBern made a nice post about it here:
    http://forums.bukkit.org/threads/in...pplied-to-an-npc-created-with-packets.188454/
     
    CaptainBern likes this.
  5. BurnBlader Okay, I took a look at your lib and tried to update it to 1.7.2 however all the
    spawn.a =
    spawn.b =
    .....
    gave me lots of error, saying that the packet isnt visible, how can I fix it?
     
  6. Offline

    xTrollxDudex

  7. xTrollxDudex Okay, I have attempted to try and make an npc, ofc - didnt work :p whats wrong with those fields?

    (NOTE : Im new to packets AND reflection...)
    Code:java
    1. public static void sendNPCToPlayer(Player p, Location loc){
    2. int id = 1;
    3. String name = "Derp";
    4. GameProfile gp = new GameProfile(name, name);
    5. Location l = p.getLocation();
    6.  
    7. PacketPlayOutNamedEntitySpawn spawn = new PacketPlayOutNamedEntitySpawn();
    8. try
    9. {
    10. ////FIELD A ID
    11. Field fa = spawn.getClass().getDeclaredField("a");
    12. fa.setAccessible(true);
    13. fa.setInt(spawn, id);
    14. fa.setAccessible(false);
    15. ////////////////////FIELD B NAME
    16. Field fb = spawn.getClass().getDeclaredField("b");
    17. fb.setAccessible(true);
    18. fb.set(spawn, gp);
    19. fb.setAccessible(false);
    20. ////////////FIELD C loc x
    21. Field fc = spawn.getClass().getDeclaredField("c");
    22. fc.setAccessible(true);
    23. fc.set(spawn, l.getBlockX() * 32);
    24. fc.setAccessible(false);
    25. //////////////FIELD D loc y
    26. Field fd = spawn.getClass().getDeclaredField("d");
    27. fd.setAccessible(true);
    28. fd.set(spawn, l.getBlockX() * 32);
    29. fd.setAccessible(false);
    30. //////////FIELD E loc z
    31. Field fe = spawn.getClass().getDeclaredField("e");
    32. fe.setAccessible(true);
    33. fe.set(spawn, l.getBlockX() * 32);
    34. fe.setAccessible(false);
    35. ///////////FIELD F yaw
    36. Field ff = spawn.getClass().getDeclaredField("f");
    37. ff.setAccessible(true);
    38. ff.set(spawn, getCompressedAngle(l.getYaw()));
    39. ff.setAccessible(false);
    40. ///////////FIELD G pitch
    41. Field fg = spawn.getClass().getDeclaredField("g");
    42. fg.setAccessible(true);
    43. fg.set(spawn, getCompressedAngle(l.getPitch()));
    44. fg.setAccessible(false);
    45. ///DONE FIELDS!
    46. DataWatcher d = new DataWatcher(null);
    47. d.a(0, (Object) (byte) 0);
    48. d.a(1, (Object) (short) 0);
    49. d.a(8, (Object) (byte) 0);
    50. //ATTEMP TO SEND?
    51. Field nameField = PacketPlayOutNamedEntitySpawn.class.getDeclaredField("i");
    52. nameField.setAccessible(true);
    53. nameField.set(spawn, d);
    54. for(Player pl : Bukkit.getOnlinePlayers()){
    55. ((CraftPlayer) pl).getHandle().playerConnection.sendPacket(spawn);
    56. }
    57. //
    58. }catch(Exception e) {
    59. e.printStackTrace();
    60. }
    61.  
    62. }
    63.  
    64. private static byte getCompressedAngle(float value) {
    65. return (byte) (value * 256.0F / 360.0F);
    66. }


    BurnBlader I used some of the stuff in your lib, I really hope its okay, if no, just tell :(
    And now for the packet =
    I do not get any errors, but the npc just wont spawn...
    Why in field C, D, E do you multiply by 32?
    Whats DataWatcher(Entity)?
    Why isnt it working? :(

    What even should I use to listen to NPC attack or interact?
     
  8. Offline

    xTrollxDudex

    Someone_Like_You
    Really, you should be using the player's handle to construct a new packet then set the fields.
     
  9. Offline

    Garris0n

  10. Garris0n xTrollxDudex BurnBlader ITS WORKING! I <3 you all,
    1 last question before I mark this as SOLVED, how do I listen to packets ? (player interact with NPC packet) w/o protocol lib?
     
  11. Offline

    Garris0n

    Comphenix Has a class called TinyProtocol that does basic packet injection here. I have no idea how to use it, so you'll have to ask him about that.
     
  12. That's fine! That is what its there for.
     
  13. Offline

    xTrollxDudex

    Someone_Like_You
    Hmm, if you don't want to depend on anything, you may have to proxy EntityPlayer's PlayerConnection.
     
  14. Garris0n Okay I will :)
    BurnBlader Youre epic :D
    xTrollxDudex I think Il give up on that interaction, looks too complicated for me :)
    ^^^^THANKS for you all!! ^^^^
    2 more things tho, I send the packet to every player that log in, is it possible to make it onEnable() and let the server send it automaticly? also - when I spawn the NPC , the NPC is like standin in the middle of 4 blocks, even if I add +0.5 to the location... anyway to fix it?
     
  15. Offline

    xTrollxDudex

  16. xTrollxDudex Thats how im sending it :) is it possible to do it on enable w/o playerjoinevent?
    Also - any ideas for the locations?...
     
  17. Offline

    xTrollxDudex

    Someone_Like_You
    Not that I know of that would be resource efficient.
    If you really want to, use a runnable that loops through all players and sends the packet in the onEnable.
     
  18. A few weeks ago I updated my own npc-lib. It can be found here: https://github.com/CaptainBern/NPC-Lib , please keep in mind it is not yet finished. Feel free to use it however...

    Edit: it allows you to detect interaction with it trough the PlayerInteractNPCEvent, you also don't have to worry about respawning it when a player joins because the lib handles everything for you.
     
  19. CaptainBern Thanks man! I really love your effect lib! Il try use it wen I get home :)
    EDIT: I just got too many question... Wonder when il run off of questions lol...
    Do you know anything about the location? Id like to know it for others packets too :) also, how do you access packets using reflection? (I have the ReflectionUtil class)
     
  20. CaptainBern Woah! CONGRATS! BukkitDev Staff! :D (IDK if its new or not, I didnt notcied it so far... haha xD)
    and thanks :p
    Also, what class do I need to copy in order to get NPC interact, I really dont understand much into all those injectors and stuff :(
    And I cant send the packet of EntityRelMoveAndLook... how do you suppost to send it?

    EDIT AGAIN! (so many edits... hopefully last edit! :p ) I played around with TinyProtocol by Comphenix(https://github.com/aadnk/ProtocolLi...com/comphenix/tinyprotocol/ExamplePlugin.java) and I succeed to detect when player interact with NPC, however I cant get how to get the NPC id and the sender ID... anyone have any ideas? what I got so far:
    Code:java
    1. private Function<Object, EnumEntityUseAction> INTERACTED = TinyProtocol.getFieldAccessor(
    2.  
    3. PacketPlayInUseEntity.class, EnumEntityUseAction.class, 0);
    4.  
    5.  
    6.  
    7. new TinyProtocol(this) {
    8.  
    9. @Override
    10.  
    11. public Object onPacketInAsync(Player sender, Object packet) {
    12.  
    13. if (packet instanceof PacketPlayInUseEntity) {
    14.  
    15. PacketPlayInUseEntity p = (PacketPlayInUseEntity) packet;
    16.  
    17. if (INTERACTED.apply(p) == EnumEntityUseAction.INTERACT){
    18.  
    19. Bukkit.broadcastMessage("Im working!");
    20.  
    21. }
    22.  
    23. }
    24.  
    25. return super.onPacketInAsync(sender, packet);
    26.  
    27. }
    28.  
    29. };
     
    CaptainBern likes this.
  21. Offline

    Comphenix

    Retrieving the sender is fairly straight forward - just use sender.getEntityId().

    As for the NPC id, take a look at the packet you are intercepting. The ID is stored in field "a", which contains the entity ID.

    This is also very easy if you use ProtocolLib. Just add the PacketWrapper classes AbstractPacket and WrapperPlayClientUseEntity to your project, and you'll be able to do the following:
    Code:java
    1. ProtocolLibrary.getProtocolManager().addPacketListener(
    2. new PacketAdapter(this, PacketType.Play.Client.USE_ENTITY) {
    3. @Override
    4. public void onPacketSending(PacketEvent event) {
    5. WrapperPlayClientUseEntity use = new WrapperPlayClientUseEntity(event.getPacket());
    6.  
    7. int senderId = event.getPlayer().getEntityId();
    8. int targetID = use.getTargetID();
    9. use.getMouse(); // ATTACK or INTERACT
    10. }
    11. });

    But the main reason you'd want to use it, is probably to stay compatible with older versions of CraftBukkit and Spigot, along with more esoteric projects such as MCPC-Plus.
     
  22. Comphenix Thanks, alltho I cant understand how to get the NPC id from a()..(PacketDataSerializer?)
    Also, is TinyProtocol may cause lags when reloading or close the server? May it cause lags for servers with 100+- players?
    btw, Im not the best with packets or wrappers and all that, is there any way to have that entity interact event (the one that uses protocolLib) in other class? (not main)
     
  23. Offline

    Comphenix

    Try using the field accessor in TinyProtocol:
    Code:java
    1. TinyProtocol.getFieldAccessor(PacketPlayInUseEntity.class, int.class, 0)

    It's unlikely, especially since onPacketInAsync() and onPacketOutAsync() is executed on an asynchronous thread. Which reminds me, do not call the Bukkit API in these methods - schedule synchronous tasks instead! The same applies to onPacketReceiving() in ProtocolLib, but not onPacketSending (as in the example), as it's executed in the main thread.

    Replace this with an instance of your plugin.
     
  24. Comphenix Thanks :) Its working! youre amazing! but the locations of the NPC's are in between 4 blocks , how do I change it? I did add 0.5+ on x and z, didnt work.
     
  25. Offline

    xTrollxDudex

  26. xTrollxDudex The location by itself while sending the packet is Location.getBlockX() * 32, which means that adding 0.5 wont do any diffrents... But Ive saw in some servers that NPC's are sitting in 1 block, not in middle of 4
     
Thread Status:
Not open for further replies.

Share This Page