Creating packets
Learn how to create and send packets to players using the Packet module.
Packet handling
Handle packets sent to or from the server.
Packet Extras
Additional packet-related features
Learn how to create and send packets to players using the Packet module.
Handle packets sent to or from the server.
Additional packet-related features
This site contains a description of the packets used in the Minecraft back-end.
Select the core version on the website on which the server is located and click on the link of this version.
First, we need to find the packet that we need. All packets located in the SERVERBOUND
section - packets are sent to the server players in the CLIENTBOUND
section - from the server to the player.
We are obviously interested in the packets section CLIENTBOUND
.
Let’s choose a packet
SET CAMERA , since it has not changed since version 1.8.
This packet allows you to set a camera for the player, similar to the camera that occurs when you click on an entity in spectator mode.
We see the following table on the website:
Packet ID | State | Bound To | Field Name | Field Type | Notes |
---|---|---|---|---|---|
0x50 | Play | Client | Camera ID | VarInt | ID of the entity to set the client’s camera to. |
This table contains the packet number, the moment of gameplay when it can be received, what the packet is linked to, and a description of its contents.
First of all, we need to find out what this packet is called on the server. To do this, we will need the first three fields:
[wrapped] packet name (by|of) id %number% [(and|,)] state %string% [(and|,)] bound %string%
ID on the site is indicated by a number in the hexadecimal, using the module Bitwise we can specify the value as described on the site, or convert the number from the site to the decimal (choose which is more convenient for you).
on load:
broadcast packet name of id 0x50 and state "play" and bound "client"
After loading script, the name of this packet will be written in the chat - PacketPlayOutCamera
.
We won’t need any more code above, it was necessary to find out the name of the packet.
Next, we need to fill the buffer with the data described in the columns Field Name
, Field Type
, Notes
.
We will fill in a new structure - ByteBuf
. It is a set of bytes into which bytes can be written and read.
The expression below is used to create an empty buffer:
empty buffer
The following expressions are used to write to the buffer:
write bytes %bytebuf% to %bytebuf%
write bool[ean] %boolean% to %bytebuf%
write uuid %string% to %bytebuf%
write string %string% to %bytebuf%
write utf[-| ]8 %string% to %bytebuf%
write position %vector% to %bytebuf%
write position %location% to %bytebuf%
write [unsigned] byte %number% to %bytebuf%
write [unsigned] short %number% to %bytebuf%
write float %number% to %bytebuf%
write double %number% to %bytebuf%
write int[eger] %number% to %bytebuf%
write long %number% to %bytebuf%
write angle %number% to %bytebuf%
write var[iable][ ]int[eger] %number% to %bytebuf%
write var[iable][ ]long %number% to %bytebuf%
Each expression provides a specific type, described in the section
Data type on wiki .
Some complex types described on the site can be made up of simple ones, so they are missing in expressions.
Packet PacketPlayOutCamera
accepts a field with the type VarInt
and a value equal to the entity ID.
To get the identifier
use the following expression .
From the table, we know that you need to write this identifier with the type VarInt
. Let’s use the necessary expression:
command packet_example:
trigger:
set {_buffer} to empty buffer
set {_entity} to target entity of player
set {_id} to entity id of {_entity}
write varint {_id} to {_buffer}
Since the table no longer contains data, we can create a packet from the buffer by its name.
Each write to the buffer shifts its Writer index
, which is the number of bytes written inside the buffer.Writer index
you can find out or change it using the following expression:
writer index of %bytebuf%
%bytebuf%'s writer index
The expression below allows you to create a packet based on the packet name and the filled buffer for subsequent sending.
[create] packet %string% (from|of|with) %bytebuf%
command packet_example:
trigger:
set {_buffer} to empty buffer
set {_entity} to target entity of player
set {_id} to entity id of {_entity}
write varint {_id} to {_buffer}
set {_packet} to create packet "PacketPlayOutCamera" with {_buffer}
We have created our first packet, it remains only to send it to the player.
The following expression is used to send packets:
send packet %packets% to %players%
The expressions below allow you to send a packet without calling an event on packet
send packet %packets% without [(trigger|call)[ing]] [the] event to %players%
send packet %packets% to %players% without [(trigger|call)[ing]] [the] event
To check the operability of the code above, aim your cursor at any entity, and then send the command /entitycam
.
After executing the command, you will be looking from the entity’s face, even if you are not in spectator mode.
This way you can create any packet by following the steps described above.
This event allows you to trigger code when a packet is received (Client -> Server
) or sent (Server -> Client
).
on packet:
on packet %packet name%:
The event can be canceled. In this case, the packet will not be received or sent (respectively).
This event has built-in expressions.
event-packet
- to receive the packetevent-player
- to get a playerevent-packet
can be replaced with set event-packet to %packet%
, provided that no execution delay was used.
After receiving the buffer from the packet, we can read the fields indicated on The Minecraft Wiki
buffer (of|from) %packet%
%packet%'s buffer
To get values from the buffer, the following expressions exist, similar to writing to the buffer
read bool[ean] from %bytebuf%
read uuid from %bytebuf%
read string from %bytebuf%
read position from %bytebuf%
read [unsigned] byte from %bytebuf%
read [unsigned] short from %bytebuf%
read float from %bytebuf%
read double from %bytebuf%
read int[eger] from %bytebuf%
read long from %bytebuf%
read angle from %bytebuf%
read var[iable][ ]int[eger] from %bytebuf%
read var[iable][ ]long from %bytebuf%
read utf[(-| )]8 [with [len[gth]]] %number% from %bytebuf%
To read utf-8 you must also specify the length of the text in bytes
Reading occurs in the same order as writing a packet, provided that the packet was not created by you.
If you created a packet and want to read it, then move its reader index to position zero.
Each reading of the buffer shifts its Reader index
, this is the number of bytes read inside the buffer.Reader index
you can find out or change it using the following expression:
reader index of %bytebuf%
%bytebuf%'s reader index
You can enable or disable handling of incoming or outgoing packets per player using the following expression.
[(handl(e|ing))|(listen[ing] [of])] (in|out)coming packets of %player%
%player%'s [(handl(e|ing))|(listen[ing] [of])] (in|out)coming packets
This is different from a UUID, an entity ID is used to identify the entity in packets.
As such, they return different values.
entity id of %entity%
%entity%'s entity id
skin value of %player%
%player%'s skin value
skin signature of %player%
%player%'s skin signature
delete skin properties of %player%
delete %player%'s skin properties
Returns a list of bytes.
It is also possible to specify the required encoding. Default is UTF-8
bytes of %string% [with charset %string%]
%string%'s bytes [with charset %string%]
This is a packet that allows you to create a sequence of packets and send them to the client at once, which provides greater speed and stability.
If you are sending many packets at once, put them in a Bundle.
bundle packet (from|of|with) %packets%