This is a tutorial that will teach you how to use packets.
What are packets?
Packets are what Minecraft uses to send information between a server and client. Each packet has a packettype. Packettypes describe what kind of information a packet holds and for what purpose that information should be used. There are two main kinds of packettypes: server and client. Server packettypes describe packets that are sent to a client from the server, and client packettypes describe packets that are received by the server from the client. Every packettype has a name that looks kinda like this: play_server_player_info. Here, play is that packettypes's group (Another classification of packets that you don't need to worry about) server means that that packettype is a server packettype, and player_info is the rest of its name.
How do we get a packet?
There are two ways you can get an actual packet: intercepting one by using a packet event, or creating one yourself. Packet events are called when a packet is either sent or received. They look like this:
on packet event %packettypes%: #do stuff
This event has the following event-values:
event-packet #(The packet being sent/received) event-packettype #(The packettype of the packet) event-player #(The player sending/receiving)
And can also be cancelled.
Packet creation is done using this simple expression:
new %packettype% packet
What information is stored in a packet, and how do we access and modify it?
Now that you have access to a packet, you can modify its information. Here's a list of all the different syntaxes for packet information:
%type% pinfo %number% of %packet% %type% array pinfo %number% of %packet% %string% pinfo %number% of %packet% %world% pentity %number% of %packet% byte pnum %number% of %packet% short pnum %number% of %packet% int pnum %number% of %packet% long pnum %number% of %packet% float pnum %number% of %packet% double pnum %number% of %packet% byte array pnum %number% of %packet% int array pnum %number% of %packet% %string% pjson %number% of %packet% %string% array pjson %number% of %packet% %string% penum %number% of %packet%
%number% is the index (starting from 0) and
%packet% is the packet you are getting information from.
%string%is the name of the enum, like "WorldBorderAction".
All these infos are settable, which is very important, as it allows you to modify the information in the packet.
How do we send and simulate receiving packets?
To send a packet that you have created, use this effect:
send %players% packet[s] %packets%
You can simulate the server receiving a packet from a player using this effect:
receive packet[s] %packets% from %players%
wiki.vg provides a list of packets, their fields, and what their fields represent. It can be useful for knowing what each pinfo of a packet means, however most of the packet names are different from their MundoSK names (which are based on their ProtocolLib names), and the fields aren't always 100% the same.
PacketWrapper created by one of ProtocolLib's developers is a library of wrappers for all the packets, It has methods that tell you exactly what each pinfo represents and sometimes also has int values telling you what an int pnum's different values mean. It was made for 1.12, but if you go through its history you will be able to see older versions of the wrappers for previous versions.
The PacketType class from ProtocolLib has a 100% up-to-date list of all of the packettypes available.
The EnumWrappers class from ProtocolLib has a list of all the enums/values that can be used in the penum expression.