Tutorial Packets, how to know which one is which?

Discussion in 'Resources' started by AlvinB, Jun 10, 2017.

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

    AlvinB

    Sooner or later, every Bukkit Developer will find that they need to use packets for something. I won't be explaining here on how to use packets or what they are (go here for that), but I'd like to touch on a simpler but annoying issue, which is, "How do I know which wiki.vg packet corresponds to what Bukkit packet?".

    The easy answer is, "Try the ones with similar names, and check if their contents match up", but there are two problems with this. First, the names don't always match up (and sometimes even hint at a completely wrong functionality), and second, the parameters don't always match up either. Wiki.vg documents what is actually being sent over the network, while the Bukkit packets may use more complicated objects as fields (an Entity for example).

    So, my solution to this is to use one of these tables which I've generated:
    1.12.1 & 1.12.2:
    https://pastebin.com/STV7DA7Q

    1.12:
    https://pastebin.com/uxbDxZpD

    NOTE: The ID's are in hexadecimal, since that's what the Packet IDs on wiki.vg are in.

    Let's do an example (for 1.12, but the principle is the same for all versions).

    We want to find the Spawn Player packet. If we look at the protocol specification, we can see that the ID is '0x05' which is essentially just 5 (the 0x can be ignored for this purpose).
    [​IMG]
    We can also see that it's in state Play and that it's clientbound.

    Next we go to the table, look under "PLAY" and then "CLIENTBOUND".
    [​IMG]
    We then find id 5 and see that the packet is called "PacketPlayOutNamedEntitySpawn".
    [​IMG]

    If anyone's curious (or perhaps wants to generate a table for a different version), here's the code I used to generate the tables:
    Code:java
    1. @SuppressWarnings("unchecked")
    2. @Override
    3. public void onEnable() {
    4. // Make just one String with our own line breaks so we don't get bukkits logger formatting in console
    5. StringBuilder builder = new StringBuilder("\n");
    6. builder.append("PLAY:\n");
    7. Field field = ReflectUtil.getDeclaredField(EnumProtocol.class, "h", true).getOrThrow();
    8. Map<EnumProtocolDirection, BiMap> map = (Map<EnumProtocolDirection, BiMap>) ReflectUtil.getFieldValue(EnumProtocol.PLAY, field).getOrThrow();
    9. for (BiMap.Entry<EnumProtocolDirection, BiMap> entry : map.entrySet()) {
    10. builder.append(entry.getKey().name()).append("\n");
    11. for (BiMap.Entry<Integer, Class<?>> entry1 : ((BiMap<Integer, Class<?>>) entry.getValue()).entrySet()) {
    12. builder.append(Integer.toHexString(entry1.getKey())).append(": ").append(entry1.getValue().getSimpleName()).append("\n");
    13. }
    14. }
    15. builder.append("\n\nHANDSHAKING:\n");
    16. map = (Map<EnumProtocolDirection, BiMap>) ReflectUtil.getFieldValue(EnumProtocol.HANDSHAKING, field).getOrThrow();
    17. for (BiMap.Entry<EnumProtocolDirection, BiMap> entry : map.entrySet()) {
    18. builder.append(entry.getKey().name()).append("\n");
    19. for (BiMap.Entry<Integer, Class<?>> entry1 : ((BiMap<Integer, Class<?>>) entry.getValue()).entrySet()) {
    20. builder.append(Integer.toHexString(entry1.getKey())).append(": ").append(entry1.getValue().getSimpleName()).append("\n");
    21. }
    22. }
    23. builder.append("\n\nSTATUS:\n");
    24. map = (Map<EnumProtocolDirection, BiMap>) ReflectUtil.getFieldValue(EnumProtocol.STATUS, field).getOrThrow();
    25. for (BiMap.Entry<EnumProtocolDirection, BiMap> entry : map.entrySet()) {
    26. builder.append(entry.getKey().name()).append("\n");
    27. for (BiMap.Entry<Integer, Class<?>> entry1 : ((BiMap<Integer, Class<?>>) entry.getValue()).entrySet()) {
    28. builder.append(Integer.toHexString(entry1.getKey())).append(": ").append(entry1.getValue().getSimpleName()).append("\n");
    29. }
    30. }
    31. builder.append("\n\nLOGIN:\n");
    32. map = (Map<EnumProtocolDirection, BiMap>) ReflectUtil.getFieldValue(EnumProtocol.LOGIN, field).getOrThrow();
    33. for (BiMap.Entry<EnumProtocolDirection, BiMap> entry : map.entrySet()) {
    34. builder.append(entry.getKey().name()).append("\n");
    35. for (BiMap.Entry<Integer, Class<?>> entry1 : ((BiMap<Integer, Class<?>>) entry.getValue()).entrySet()) {
    36. builder.append(Integer.toHexString(entry1.getKey())).append(": ").append(entry1.getValue().getSimpleName()).append("\n");
    37. }
    38. }
    39. System.out.println(builder.toString());
    40. }
     
    Last edited: Dec 11, 2017
    Speaw, barpec12, Reflxction and 4 others like this.
  2. Offline

    AlvinB

    Updated this to 1.12.1.
     
  3. Offline

    Speaw

    nice tutorial thank you..
     
Thread Status:
Not open for further replies.

Share This Page