Tutorial by: Tlatoani

This is a tutorial that will teach you how to use packets with ThatPacketAddon, a new addon focused solely on packet manipulation. The information in this tutorial is essentially identical to the previous tutorial on packets except that the fields now use ThatPacketAddon's new syntax for packet fields and there is now a section on packet field aliases.

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 packettype'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% [with (lowest|low|normal|high|highest|monitor) priority]:
    #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.

When using a packet event, you can optionally specify to listen for it with a certain priority. Triggers with higher priorities will be called later, so the following code:

on packet event play_server_chat with high priority:
    send "High!!!!" to console

on packet event play_server_chat with low priority:
    send "low...." to console

on packet event play_server_chat with monitor priority:
    send "mOnItOr" to console

the following will be printed:


Triggers have normal priority by default.

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?

Packets have various fields that store their information. (More generally, in Java and other programming languages, all objects have fields which contain their data). ProtocolLib, and ThatPacketAddon using ProtocolLib, sees these fields in a certain order, meaning that you can number each field, and so when accessing these fields you identify them by their index.

Let's look at the first packet field expression as an example:
Object Field of Packet

object [packet] field [%number%] [of %packet%]

The number expression is the index of the field. You can actually leave it out, and it will be assumed to be 0, which identifies the first packet field (remember that in programming outside of Skript, indexing tends to start at 0). However, you should really only leave out the explicit index if the packet only contains a single field, as it may be confusing otherwise.

The packet expression identifies which packet you're looking at the field of, as you might expect. If you leave the packet expression out, it will be assumed to be event-packet (and if there is no event-packet in the surrounding context, that expression won't load).

So, for example, object field would refer to the first packet field in event-packet, and could also be written as object field 0 in event-packet; object field of {_packet} would refer to the first packet field in {_packet}; object field 3 would refer to the fourth packet field in event-packet; and object field 7 in {_packet} would refer to the eight packet field in {_packet}.

It's extremely important to note that you can set these packet fields - that's the whole point of doing packet manipulation.

As to the Object Field of Packet expression however, you will most likely never use it, because we generally also identify fields by their type. Just like Skript has types, Java also has types, or, as they're called in Java, classes, and we need to identify packet fields by their type because that clarifies what the field refers to and also allows ThatPacketAddon to make the proper conversion between the Java representation of a Skript type and the actual Java class of the field.

Here's an example of one of the packet field expressions that you most likely will be using:
String Field of Packet

string [packet] field [%number%] [of %packet%]

Notice that the syntax is almost identical to the syntax for the Object Field of Packet expression, but with string instead of object. Now, the expression refers to a string field of the specified packet. For example, string field will refer to the first string field in event-packet, even if that first string field isn't the first of all the fields in event-packet.

One thing that might seem confusing is that quite a few different packet fields provided by ThatPacketAddon have the same Skript type. This is because Minecraft internally tends to use a lot more classes than Skript has or needs; for example, Itemstack Field of Packet, Block Field of Packet, Blockdata Field of Packet, and Item Field of Packet all have the type itemstack in Skript, because, for example, Block Field of Packet refers to fields that internally describe the material of a block, but Skript doesn't have a separate material type, so the field is conveniently represented in Skript as an itemstack which has the appropriate material.

With that out of the way, here is an extensive list of the packet field expressions in ThatPacketAddon. If you want to look at the specific documentation for any of these, you can search them on Skript Hub or skUnity, or you can also use the /packetaddon doc command (example: /packetaddon doc string field of packet. /packetaddon doc str f will also work).

Object Field of Packet object field [%number%] [of %packet%]
Boolean Field of Packet boolean field [%number%] [of %packet%]
String Field of Packet string field [%number%] [of %packet%]
String Array Field of Packet string array field [%number%] [of %packet%]
Byte Field of Packet byte field [%number%] [of %packet%]
Short Field of Packet short field [%number%] [of %packet%]
Int Field of Packet int field [%number%] [of %packet%]
Long Field of Packet long field [%number%] [of %packet%]
Float Field of Packet float field [%number%] [of %packet%]
Double Field of Packet double field [%number%] [of %packet%]
Byte Array Field of Packet byte array field [%number%] [of %packet%]
Int Array Field of Packet int array field [%number%] [of %packet%]
Itemstack Field of Packet itemstack field [%number%] [of %packet%]
Itemstack Array Field of Packet itemstack array field [%number%] [of %packet%]
Itemstack List Field of Packet itemstack list field [%number%] [of %packet%]
Block Field of Packet block field [%number%] [of %packet%]
Blockdata Field of Packet blockdata field [%number%] [of %packet%]
Item Field of Packet item field [%number%] [of %packet%]
Location Field of Packet location field [%number%] [of %packet%]
Location Collection Field of Packet location collection field [%number%] [of %packet%]
UUID Field of Packet uuid field [%number%] [of %packet%]
Worldtype Field of Packet worldtype field [%number%] [of %packet%]
Minecraft Key Field of Packet minecraft key field [%number%] [of %packet%]
Collection Field of Packet collection field [%number%] [of %packet%]
Byte Buffer Field of Packet byte buffer field [%number%] [of %packet%]
Gamemode Field of Packet gamemode field [%number%] [of %packet%]
Difficulty Field of Packet difficulty field [%number%] [of %packet%]
Profile Field of Packet profile field [%number%] [of %packet%]
PlayerInfoData List Field of Packet playerinfodata list field [%number%] [of %packet%]
Server Ping Field of Packet server ping field [%number%] [of %packet%]
Vector Field of Packet vector field [%number%] [of %packet%]
Dimension ID Field of Packet dimension id field [%number%] [of %packet%]
Chat Component Field of Packet chat component field [%number%] [of %packet%]
Chat Component Array Field of Packet chat component array field [%number%] [of %packet%]
NBT Field of Packet nbt field [%number%] [of %packet%]
NBT List Field of Packet nbt list field [%number%] [of %packet%]
Undocumented data watcher field [%number%] [of %packet%]
Undocumented watchable collection field [%number%] [of %packet%]

Additionally, there are many enum fields used by Minecraft, meaning fields that have a finite amount of values identified by their names. These are easy to handle and there are many of them so ThatPacketAddon automatically generates packet field expressions for them. Here is a list of them taken on ProtocolLib version 4.4.0:

ChatType Field of Packet chattype field [%number%] [of %packet%]
ChatVisibility Field of Packet chatvisibility field [%number%] [of %packet%]
ClientCommand Field of Packet clientcommand field [%number%] [of %packet%]
CombatEventType Field of Packet combateventtype field [%number%] [of %packet%]
Direction Field of Packet direction field [%number%] [of %packet%]
EntityUseAction Field of Packet entityuseaction field [%number%] [of %packet%]
Hand Field of Packet hand field [%number%] [of %packet%]
ItemSlot Field of Packet itemslot field [%number%] [of %packet%]
NativeGameMode Field of Packet nativegamemode field [%number%] [of %packet%]
Particle Field of Packet particle field [%number%] [of %packet%]
PlayerAction Field of Packet playeraction field [%number%] [of %packet%]
PlayerDigType Field of Packet playerdigtype field [%number%] [of %packet%]
PlayerInfoAction Field of Packet playerinfoaction field [%number%] [of %packet%]
ResourcePackStatus Field of Packet resourcepackstatus field [%number%] [of %packet%]
ScoreboardAction Field of Packet scoreboardaction field [%number%] [of %packet%]
SoundCategory Field of Packet soundcategory field [%number%] [of %packet%]
TitleAction Field of Packet titleaction field [%number%] [of %packet%]
WorldBorderAction Field of Packet worldborderaction field [%number%] [of %packet%]

How do we send and simulate receiving packets?

To send a packet that you have created, use this effect:
Send Packet

send %players% packet[s] %packets%
send packet[s] %packets% to %players%

You can simulate the server receiving a packet from a player using this effect:
Receive Packet

receive packet[s] %packets% from %players%

Packet Field Aliases

When using packet field expressions, you may feel like it's kind of confusing to have to refer to fields by only their type and index, which don't necessarily reveal much about what the field actually describes. You might look up what index a certain field is at, and then forget, so you either have to look it up again or try to figure it out again. Worry no longer! ThatPacketAddon has the perfect solution to your problem with packet field aliases.

Packet field aliases allow you to give alternative syntaxes to the packet fields of certain packettypes. The general format is like this:

packet field aliases for %packettype%:
    <new syntax 1> = <old syntax 1>
    <new syntax 2> = <old syntax 2>
    # etc.

Note that not all fields of the packettype have to be given alternative syntaxes; you can do as many as you like, or even just one.

Here's an example using the play_server_world_border packettype:

packet field aliases for play_server_world_border:
    border action of %packet% = worldborderaction field of %packet%
    border portal teleport boundary of %packet% = int field 0 of %packet%
    border center x[-coord] of %packet% = double field 0 of %packet%
    border center z[-coord] of %packet% = double field 1 of %packet%
    border old radius of %packet% = double field 2 of %packet%
    border radius of %packet% = double field 3 of %packet%
    border speed of %packet% = long field 0 of %packet%
    border warning time [span|length] of %packet% = int field 1 of %packet%
    border warning (distance|blocks) of %packet% = int field 2 of %packet%

# makes it so that if the player comes within 36 blocks of the border, their screen will be tinted red
on packet event play_server_world_border:
    set border warning blocks of event-packet to 36

You can also make the packet expression (%packet%) optional in your new syntax, so rewriting our previous example:packet field aliases for play_server_world_border:

packet field aliases for play_server_world_border:
    # ...
    border warning (distance|blocks) [of %packet%] = int field 2 of %packet%

# makes it so that if the player comes within 36 blocks of the border, their screen will be tinted red
on packet event play_server_world_border:
    set border warning blocks to 36

Helpful Resources

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's kept up-to-date with the latest Minecraft version but you can go through its history 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.

Did you find Tlatoani's tutorial helpful?

You must be logged in to comment