* added a null check to fix crash, expose internal latency value (its buggy) * fix latency calculations * sending packets from c# * world save event, move shutdown def, move called location of shutdown, expose FourKit.FireEvent * add docs --------- Co-authored-by: sylvessa <225480449+sylvessa@users.noreply.github.com>
43 KiB
@page sending-packets Sending Packets
This page covers how to manually send raw packets to clients using the \ref Minecraft.Server.FourKit.Experimental.PlayerConnection "PlayerConnection" API. This is an experimental feature for advanced use cases where you need to send data that FourKit doesnt yet wrap in its API.
This API is experimental and may change. You are responsible for constructing valid packets!!! malformed data can crash or disconnect the client.
Also please keep in mind, some of this info may not be accurate! Feel free to improve this by contributing on the Github.
@section packet_overview Overview
Every Minecraft packet on the wire looks like this:
| Field | Size | Description |
|---|---|---|
| Size | 4 bytes (big-endian) | Total length of the remaining data (packet ID + payload). Written automatically by the server.. you do NOT include it. |
| Packet ID | 1 byte | Which packet this is. Only the low byte matters on the wire even though IDs are int in source. |
| Payload | variable | The rest of the packet data, format depends on the packet ID. |
When you call PlayerConnection.send(byte[] data), the server prepends the 4-byte big-endian size header for you. Your byte array should start with the packet ID byte followed by the payload.
@section wire_data_types Wire Data Types
All multi-byte values are big-endian (most significant byte first).
| Type | Size | Description |
|---|---|---|
byte |
1 | Unsigned 8-bit integer (0-255). |
bool |
1 | 0 = false, non-zero = true. |
short |
2 | Signed 16-bit integer. |
int |
4 | Signed 32-bit integer. |
long |
8 | Signed 64-bit integer. |
float |
4 | IEEE 754 single-precision float. |
utf |
2 + n | Modified UTF-8 string: short byte-length prefix followed by that many bytes of data. See \ref string_encoding "String Encoding". |
item |
variable | Item data (item ID, count, damage). See \ref item_data "Item Data". |
metadata |
variable | Entity metadata (SynchedEntityData). See \ref metadata_encoding "Metadata Encoding". |
@section string_encoding String Encoding
Strings use modified UTF-8 encoding:
- A
short(2 bytes, big-endian) containing the byte length of the string data. - That many bytes of modified-UTF8 characters.
For most ASCII text (chat messages, names, etc.) this is identical to standard UTF-8. A helper to write a string:
static int WriteUTF(byte[] buffer, int offset, string text)
{
byte[] utf8 = System.Text.Encoding.UTF8.GetBytes(text);
WriteShort(buffer, offset, (short)utf8.Length);
Buffer.BlockCopy(utf8, 0, buffer, offset + 2, utf8.Length);
return 2 + utf8.Length; // total bytes written
}
@section item_data Item Data
Several container packets include serialized item data. The wire format for a single item slot is:
| Field | Type | Description |
|---|---|---|
| id | short |
Item ID. -1 means the slot is empty (no further fields follow). |
| count | byte |
Stack size. |
| damage | short |
Damage/metadata value. |
If the item ID is -1, only the short is written (2 bytes for an empty slot). Otherwise all three fields are written (5 bytes).
@section metadata_encoding Metadata Encoding (SynchedEntityData)
Entity metadata is used in packets like AddMobPacket (24), AddPlayerPacket (20), and SetEntityDataPacket (40). It's a list of typed key-value entries terminated by 0x7F.
Each entry starts with a 1-byte header:
- Bits 5-7 (mask
0xE0): Type ID, shifted right by 5. - Bits 0-4 (mask
0x1F): Data slot ID (max 31).
So the header byte is (type << 5) | (id & 0x1F).
The value immediately follows, sized based on the type:
| Type ID | Name | Value Size |
|---|---|---|
| 0 | Byte | 1 byte |
| 1 | Short | 2 bytes |
| 2 | Int | 4 bytes |
| 3 | Float | 4 bytes |
| 4 | String | utf (2-byte length prefix + string data) |
| 5 | ItemInstance | item (see \ref item_data "Item Data") |
After all entries, write 0x7F as the EOF marker.
@subsubsection metadata_data_ids Common Data Slot IDs
These are the data slot IDs used by the entity class hierarchy. When constructing metadata, define these in order and use the correct type.
Entity (base):
| ID | Type | Name | Description |
|---|---|---|---|
| 0 | Byte | DATA_SHARED_FLAGS | Bitfield: bit 0=on fire, 1=sneaking, 3=sprinting, 4=using item, 5=invisible, 6=idle anim |
| 1 | Short | DATA_AIR_SUPPLY | Air supply (default 300, max 300) |
LivingEntity:
| ID | Type | Name | Description |
|---|---|---|---|
| 6 | Float | DATA_HEALTH | Health value (default 1.0) |
| 7 | Int | DATA_EFFECT_COLOR | Potion effect color (default 0) |
| 8 | Byte | DATA_EFFECT_AMBIENCE | Potion effect ambience (default 0) |
| 9 | Byte | DATA_ARROW_COUNT | Number of arrows stuck in entity (default 0) |
Mob:
| ID | Type | Name | Description |
|---|---|---|---|
| 10 | String | DATA_CUSTOM_NAME | Custom name tag (default "") |
| 11 | Byte | DATA_CUSTOM_NAME_VISIBLE | Show name tag (0 or 1, default 0) |
For example, to write metadata for a basic mob with a custom name:
// helper to write a metadata entry header
static void WriteMetaHeader(byte[] buffer, int offset, int type, int id)
{
buffer[offset] = (byte)((type << 5) | (id & 0x1F));
}
// build metadata for a mob with a visible custom name "booty"
// enity base: flags=0, air=300
// livingentity: health=20.0, effectColor=0, effectAmbience=0, arrowCount=0
// mob: customName="booty", customNameVisible=1
byte[] nameBytes = System.Text.Encoding.UTF8.GetBytes("booty");
int metaSize = (1+1) + (1+2) + (1+4) + (1+4) + (1+1) + (1+1)
+ (1 + 2 + nameBytes.Length) + (1+1) + 1; // +1 for EOF
byte[] meta = new byte[metaSize];
int pos = 0;
// Entity
WriteMetaHeader(meta, pos, 0, 0); pos++; meta[pos++] = 0; // flags = 0
WriteMetaHeader(meta, pos, 1, 1); pos++; WriteShort(meta, pos, 300); pos += 2; // air supply
// LivingEntity
WriteMetaHeader(meta, pos, 3, 6); pos++; WriteFloat(meta, pos, 20.0f); pos += 4; // health
WriteMetaHeader(meta, pos, 2, 7); pos++; WriteInt(meta, pos, 0); pos += 4; // effect color
WriteMetaHeader(meta, pos, 0, 8); pos++; meta[pos++] = 0; // effect ambience
WriteMetaHeader(meta, pos, 0, 9); pos++; meta[pos++] = 0; // arrow count
// Mob
WriteMetaHeader(meta, pos, 4, 10); pos++;
pos += WriteUTF(meta, pos, "booty"); // custom name
WriteMetaHeader(meta, pos, 0, 11); pos++; meta[pos++] = 1; // name visible
meta[pos] = 0x7F; // EOF marker
@section writing_data Writing Packet Data
Helper methods for writing big-endian values into a byte[] buffer:
static void WriteByte(byte[] buffer, int offset, int value)
{
buffer[offset] = (byte)(value & 0xFF);
}
static void WriteBool(byte[] buffer, int offset, bool value)
{
buffer[offset] = (byte)(value ? 1 : 0);
}
static void WriteShort(byte[] buffer, int offset, short value)
{
buffer[offset] = (byte)((value >> 8) & 0xFF);
buffer[offset + 1] = (byte)(value & 0xFF);
}
static void WriteInt(byte[] buffer, int offset, int value)
{
buffer[offset] = (byte)((value >> 24) & 0xFF);
buffer[offset + 1] = (byte)((value >> 16) & 0xFF);
buffer[offset + 2] = (byte)((value >> 8) & 0xFF);
buffer[offset + 3] = (byte)(value & 0xFF);
}
static void WriteFloat(byte[] buffer, int offset, float value)
{
byte[] bytes = BitConverter.GetBytes(value);
if (BitConverter.IsLittleEndian)
Array.Reverse(bytes);
Buffer.BlockCopy(bytes, 0, buffer, offset, 4);
}
static void WriteLong(byte[] buffer, int offset, long value)
{
buffer[offset] = (byte)((value >> 56) & 0xFF);
buffer[offset + 1] = (byte)((value >> 48) & 0xFF);
buffer[offset + 2] = (byte)((value >> 40) & 0xFF);
buffer[offset + 3] = (byte)((value >> 32) & 0xFF);
buffer[offset + 4] = (byte)((value >> 24) & 0xFF);
buffer[offset + 5] = (byte)((value >> 16) & 0xFF);
buffer[offset + 6] = (byte)((value >> 8) & 0xFF);
buffer[offset + 7] = (byte)(value & 0xFF);
}
static void WriteEmptyItem(byte[] buffer, int offset)
{
WriteShort(buffer, offset, (short)-1);
}
static void WriteItem(byte[] buffer, int offset, short id, byte count, short damage)
{
WriteShort(buffer, offset, id);
buffer[offset + 2] = count;
WriteShort(buffer, offset + 3, damage);
}
@section precision_scaling Precision Scaling
Some fields use fixed-point encoding integers on the wire representing floats/doubles with a multiplier applied:
| Data Type | Multiplier | Wire Type | Description |
|---|---|---|---|
| Entity position | x 32 | int |
(int)(position * 32). 1/32 block precision. |
| Sound position | x 8 | int |
(int)(position * 8). 1/8 block precision. |
| Rotation | x 256 / 360 | byte |
(byte)(angle * 256.0 / 360.0). |
| Velocity | x 8000 | short |
(short)(velocity * 8000.0), clamped to +/-3.9 blocks/tick before encoding. |
int wireX = (int)(player.getLocation().getX() * 32);
int wireY = (int)(player.getLocation().getY() * 32);
int wireZ = (int)(player.getLocation().getZ() * 32);
byte wireYaw = (byte)(player.getLocation().getYaw() * 256.0 / 360.0);
byte wirePitch = (byte)(player.getLocation().getPitch() * 256.0 / 360.0);
@section example_sound Example: Playing a Sound Effect
Sends a LevelSoundPacket (ID 62) to play a ghast scream at the player's location whenever they chat.
[EventHandler]
public void onPlayerChat(PlayerChatEvent e)
{
// LevelSoundPacket layout:
// [0] byte packet ID (62)
// [1..4] int sound type
// [5..8] int x * 8
// [9..12] int y * 8
// [13..16] int z * 8
// [17..20] float volume
// [21..24] float pitch
byte[] buffer = new byte[25];
buffer[0] = (byte)62; // packet id
WriteInt(buffer, 1, (int)19); // eSoundType_MOB_GHAST_SCREAM (Sound.GHAST_SCREAM)
WriteInt(buffer, 5, (int)(e.getPlayer().getLocation().getX() * 8));
WriteInt(buffer, 9, (int)(e.getPlayer().getLocation().getY() * 8));
WriteInt(buffer, 13, (int)(e.getPlayer().getLocation().getZ() * 8));
WriteFloat(buffer, 17, 10); // volume
WriteFloat(buffer, 21, 1); // pitch
e.getPlayer().getConnection().send(buffer);
}
Sound type IDs correspond to the \ref Minecraft.Server.FourKit.Sound "Sound" enum. Cast any Sound value to int to get the wire value, for example (int)Sound.GHAST_SCREAM is 19.
@section example_gamee Example: Changing the Game Mode
GameEventPacket (ID 70) notifies the client of game state changes.
[EventHandler]
public void onJoin(PlayerJoinEvent e)
{
// layout:
// [0] byte packet ID (70)
// [1] byte event type
// [2] byte parameter
byte[] buffer = new byte[3];
buffer[0] = (byte)70; // packet id
buffer[1] = (byte)3; // CHANGE_GAME_MODE
buffer[2] = (byte)1; // 0 = Survival, 1 = Creative, 2 = Adventure
e.getPlayer().getConnection().send(buffer);
}
@section example_entity_teleport Example: Teleporting an Entity (Client-Side)
TeleportEntityPacket (ID 34) moves an entity to an absolute position on the client.
// Teleport entity 42 to (100.5, 64.0, -200.25)
byte[] buffer = new byte[17]
buffer[0] = (byte)34; // packet id
WriteShort(buffer, 1, (short)42); // entity id
WriteInt(buffer, 3, (int)(100.5 * 32)); // x * 32
WriteInt(buffer, 7, (int)(64.0 * 32)); // y * 32
WriteInt(buffer, 11, (int)(-200.25 * 32)); // z * 32
buffer[15] = (byte)(90.0 * 256.0 / 360.0); // yRot
buffer[16] = (byte)(0.0 * 256.0 / 360.0); // xRot
player.getConnection().send(buffer);
@section example_set_time Example: Setting the World Time
SetTimePacket (ID 4) updates the client's world time.
// set time to noon (6000 ticks)
byte[] buffer = new byte[17]
buffer[0] = (byte)4; // packet id
WriteLong(buffer, 1, 6000L); // game time (total ticks elapsed)
WriteLong(buffer, 9, 6000L); // day time (time of day, 0-24000)
player.getConnection().send(buffer);
@section example_health Example: Updating Health Display
SetHealthPacket (ID 8) updates the client's health, food, and saturation display.
// set health to 20 (full), food to 20 (full), saturation to 5.0
byte[] buffer = new byte[12];
buffer[0] = (byte)8; // packet id
WriteFloat(buffer, 1, 20.0f); // health
WriteShort(buffer, 5, (short)20); // food
WriteFloat(buffer, 7, 5.0f); // saturation
buffer[11] = (byte)0; // damage source (0 = unknown)
player.getConnection().send(buffer);
@section example_abilities Example: Setting Player Abilities
PlayerAbilitiesPacket (ID 202) updates the player's ability flags and speeds.
// enable flying for the player
byte[] buffer = new byte[10];
buffer[0] = (byte)202; // packet id
// 0x01=invulnerable, 0x02=flying, 0x04=canFly, 0x08=instabuild (creative)
buffer[1] = (byte)(0x02 | 0x04); // flying + canFly
WriteFloat(buffer, 2, 0.05f); // fly speed (default 0.05)
WriteFloat(buffer, 6, 0.1f); // walk speed (default 0.1)
player.getConnection().send(buffer);
@section example_explosion Example: Creating an Explosion Effect
ExplodePacket (ID 60) creates a client-side explosion with optional block destruction and knockback.
// create an explosion at (100.0, 64.0, 200.0) with radius 4.0 and no destroyed blocks
byte[] buffer = new byte[46];
buffer[0] = (byte)60; // packet id
buffer[1] = (byte)0; // knockbackOnly = false (full explosion with position data)
// position (double precision, 8 bytes each)
byte[] xBytes = BitConverter.GetBytes(100.0);
byte[] yBytes = BitConverter.GetBytes(64.0);
byte[] zBytes = BitConverter.GetBytes(200.0);
Buffer.BlockCopy(xBytes, 0, buffer, 2, 8);
Buffer.BlockCopy(yBytes, 0, buffer, 10, 8);
Buffer.BlockCopy(zBytes, 0, buffer, 18, 8);
WriteFloat(buffer, 26, 4.0f); // radius
WriteInt(buffer, 30, 0); // destroyed block count (0 = no blocks)
// knockback velocity applied to player
WriteFloat(buffer, 34, 0.0f); // knockback X
WriteFloat(buffer, 38, 0.5f); // knockback Y (push player up)
WriteFloat(buffer, 42, 0.0f); // knockback Z
player.getConnection().send(buffer);
@section example_xp Example: Setting the XP Bar
SetExperiencePacket (ID 43) updates the XP bar.
// Set XP bar to 50% progress, level 10, total 300 XP
byte[] buffer = new byte[1 + 4 + 2 + 2]; // 9 bytes
buffer[0] = (byte)43; // packet id
WriteFloat(buffer, 1, 0.5f); // bar progress (0.0 to 1.0)
WriteShort(buffer, 5, (short)10); // level
WriteShort(buffer, 7, (short)300); // total XP points
player.getConnection().send(buffer);
@section packet_reference Complete packet reference
All server-to-client packet layouts. The packet ID byte is always buffer[0] and is not listed in the field tables below. only the payload after the ID is shown.
@subsection packet_ref_general General / Connection Packets
@subsubsection pkt_0 Packet 0 - KeepAlivePacket
Connection keepalive. The client echoes this back.
| Offset | Type | Field | Description |
|---|---|---|---|
| 0 | int |
id | Keepalive ID. The client should respond with the same value. |
Total payload: 4 bytes.
@subsubsection pkt_3 Packet 3 - ChatPacket
Send a chat/system message to the client.
| Offset | Type | Field | Description |
|---|---|---|---|
| 0 | short |
messageType | Message type enum value. |
| 2 | short |
packedCounts | Packed field: high nibble = string arg count, low nibble = int arg count. Computed as (stringCount << 4) | intCount. |
| 4 | utf[] |
stringArgs | Variable number of utf strings (the message text, source name, item name, etc). |
| ... | int[] |
intArgs | Variable number of int values (for example source entity type). |
Total payload: variable. For a simple chat message, messageType = 0, one string arg (the message), zero int args. The packed counts would be (1 << 4) | 0 = 0x0010.
@subsubsection pkt_255 Packet 255 - DisconnectPacket
Disconnect the client.
| Offset | Type | Field | Description |
|---|---|---|---|
| 0 | int |
reason | Disconnect reason code. |
Total payload: 4 bytes.
@subsection packet_ref_world World & Environment Packets
@subsubsection pkt_4 Packet 4 - SetTimePacket
Set world time.
| Offset | Type | Field | Description |
|---|---|---|---|
| 0 | long |
gameTime | Total game time in ticks (monotonically increasing). |
| 8 | long |
dayTime | Time of day in ticks (0-24000 range). |
Total payload: 16 bytes.
@subsubsection pkt_6 Packet 6 - SetSpawnPositionPacket
Set the world spawn point.
| Offset | Type | Field | Description |
|---|---|---|---|
| 0 | int |
x | Spawn X coordinate. |
| 4 | int |
y | Spawn Y coordinate. |
| 8 | int |
z | Spawn Z coordinate. |
Total payload: 12 bytes.
@subsubsection pkt_9 Packet 9 - RespawnPacket
Sent on respawn or dimension change.
| Offset | Type | Field | Description |
|---|---|---|---|
| 0 | byte |
dimension | Dimension ID (0=Overworld, -1=Nether, 1=End). |
| 1 | byte |
gameType | Game mode ID (0=Survival, 1=Creative, 2=Adventure). |
| 2 | short |
mapHeight | World height. |
| 4 | utf |
levelType | Level type name (for example "DEFAULT", "FLAT"). |
| ... | long |
mapSeed | World seed. |
| ... | byte |
difficulty | Difficulty (0=Peaceful, 1=Easy, 2=Normal, 3=Hard). |
| ... | bool |
newSeaLevel | Whether the new sea level is active. |
| ... | short |
newEntityId | The player's new entity ID. |
| ... | short |
xzSize | World XZ size. |
| ... | byte |
hellScale | Nether scale factor. |
Total payload: variable (depends on level type string length).
@subsubsection pkt_53 Packet 53 - TileUpdatePacket
Update a single block.
| Offset | Type | Field | Description |
|---|---|---|---|
| 0 | int |
x | Block X coordinate. |
| 4 | byte |
y | Block Y coordinate (0-255). |
| 5 | int |
z | Block Z coordinate. |
| 9 | short |
block | Block type ID. |
| 11 | byte |
dataLevel | Block data/metadata value. |
Total payload: 12 bytes.
@subsubsection pkt_54 Packet 54 - TileEventPacket
Trigger a block action (note blocks, pistons, chests).
| Offset | Type | Field | Description |
|---|---|---|---|
| 0 | int |
x | Block X coordinate. |
| 4 | short |
y | Block Y coordinate. |
| 6 | int |
z | Block Z coordinate. |
| 10 | byte |
b0 | Action parameter 1 (depends on block type). |
| 11 | byte |
b1 | Action parameter 2 (depends on block type). |
| 12 | short |
tile | Block type ID. |
Total payload: 14 bytes.
@subsubsection pkt_55 Packet 55 - TileDestructionPacket
Show a block breaking animation (crack overlay).
| Offset | Type | Field | Description |
|---|---|---|---|
| 0 | int |
id | Breaker entity ID. |
| 4 | int |
x | Block X coordinate. |
| 8 | int |
y | Block Y coordinate. |
| 12 | int |
z | Block Z coordinate. |
| 16 | byte |
state | Destroy stage (0-9). Any other value removes the overlay. |
Total payload: 17 bytes.
@subsubsection pkt_60 Packet 60 - ExplodePacket
Explosion with optional block destruction and knockback.
| Offset | Type | Field | Description |
|---|---|---|---|
| 0 | bool |
knockbackOnly | If true, only knockback fields follow (no position/radius/blocks). |
If knockbackOnly is false (typical explosion):
| Offset | Type | Field | Description |
|---|---|---|---|
| 1 | double |
x | Explosion center X. |
| 9 | double |
y | Explosion center Y. |
| 17 | double |
z | Explosion center Z. |
| 25 | float |
radius | Explosion radius. |
| 29 | int |
count | Number of destroyed block offsets. |
| 33 | byte[count*3] |
offsets | For each block: 3 signed bytes (dx, dy, dz) relative to the center. |
| ... | float |
knockbackX | Player knockback velocity X. |
| ... | float |
knockbackY | Player knockback velocity Y. |
| ... | float |
knockbackZ | Player knockback velocity Z. |
If knockbackOnly is true (just apply knockback, no visual explosion):
| Offset | Type | Field | Description |
|---|---|---|---|
| 1 | float |
knockbackX | Player knockback velocity X. |
| 5 | float |
knockbackY | Player knockback velocity Y. |
| 9 | float |
knockbackZ | Player knockback velocity Z. |
Total payload: variable.
@subsubsection pkt_61 Packet 61 - LevelEventPacket
World event (sounds, particles, door effects, etc).
| Offset | Type | Field | Description |
|---|---|---|---|
| 0 | int |
type | Event type ID (for example 1000=click sound, 1005=bow sound, 2000=smoke, 2001=break block). |
| 4 | int |
x | Block X coordinate. |
| 8 | byte |
y | Block Y coordinate. |
| 9 | int |
z | Block Z coordinate. |
| 13 | int |
data | Event-specific data (for example block ID for break effect, direction for smoke). |
| 17 | bool |
globalEvent | If true, event is global (all players hear it regardless of distance). |
Total payload: 18 bytes.
@subsubsection pkt_62 Packet 62 - LevelSoundPacket
Play a sound at a position. Positions use x8 scaling.
| Offset | Type | Field | Description |
|---|---|---|---|
| 0 | int |
soundId | Sound type ID. Maps to the \ref Minecraft.Server.FourKit.Sound "Sound" enum. |
| 4 | int |
x | X coordinate * 8. |
| 8 | int |
y | Y coordinate * 8. |
| 12 | int |
z | Z coordinate * 8. |
| 16 | float |
volume | Sound volume (1.0 = normal). |
| 20 | float |
pitch | Sound pitch (1.0 = normal). |
Total payload: 24 bytes.
@subsubsection pkt_63 Packet 63 - LevelParticlesPacket
Spawn particles at a position.
| Offset | Type | Field | Description |
|---|---|---|---|
| 0 | utf |
name | Particle name string (for example "flame", "smoke", "heart"). |
| ... | float |
x | Center X coordinate. |
| ... | float |
y | Center Y coordinate. |
| ... | float |
z | Center Z coordinate. |
| ... | float |
xDist | Random X offset range. |
| ... | float |
yDist | Random Y offset range. |
| ... | float |
zDist | Random Z offset range. |
| ... | float |
maxSpeed | Maximum particle speed. |
| ... | int |
count | Number of particles to spawn. |
Total payload: variable (depends on particle name string length) + 32 bytes for the fixed fields.
@subsubsection pkt_70 Packet 70 - GameEventPacket
Game state change notification.
| Offset | Type | Field | Description |
|---|---|---|---|
| 0 | byte |
event | Event type. |
| 1 | byte |
param | Event parameter. |
Event types:
| Value | Name | Parameter |
|---|---|---|
| 0 | No Bed | (unused) |
| 1 | Start Rain | (unused) |
| 2 | Stop Rain | (unused) |
| 3 | Change Game Mode | 0=Survival, 1=Creative, 2=Adventure |
| 4 | Win Game | 0=show credits, 1=just respawn |
Total payload: 2 bytes.
@subsubsection pkt_130 Packet 130 - SignUpdatePacket
Update sign text.
| Offset | Type | Field | Description |
|---|---|---|---|
| 0 | int |
x | Sign X coordinate. |
| 4 | short |
y | Sign Y coordinate. |
| 6 | int |
z | Sign Z coordinate. |
| 10 | bool |
verified | Whether the sign text has been verified. |
| 11 | bool |
censored | Whether the sign text has been censored. |
| 12 | utf |
line1 | First line of text. |
| ... | utf |
line2 | Second line of text. |
| ... | utf |
line3 | Third line of text. |
| ... | utf |
line4 | Fourth line of text. |
Total payload: variable (12 bytes fixed + 4 * utf strings).
@subsection packet_ref_entity Entity Packets
@subsubsection pkt_8 Packet 8 - SetHealthPacket
Update health, food, and saturation.
| Offset | Type | Field | Description |
|---|---|---|---|
| 0 | float |
health | Current health (0.0-20.0, 20 = full). |
| 4 | short |
food | Food level (0-20). |
| 6 | float |
saturation | Food saturation level. |
| 10 | byte |
damageSource | Damage source type (for telemetry). |
Total payload: 11 bytes.
@subsubsection pkt_18 Packet 18 - AnimatePacket
Play an entity animation.
| Offset | Type | Field | Description |
|---|---|---|---|
| 0 | int |
entityId | Entity ID. |
| 4 | byte |
action | Animation type (1=swing arm, 2=damage, 3=leave bed, 104=crouch, 105=uncrouch). |
Total payload: 5 bytes.
@subsubsection pkt_20 Packet 20 - AddPlayerPacket
Spawn a named player entity.
| Offset | Type | Field | Description |
|---|---|---|---|
| 0 | int |
entityId | Entity ID. |
| 4 | utf |
name | Player name. |
| ... | int |
x | X coordinate * 32 (fixed-point). |
| ... | int |
y | Y coordinate * 32 (fixed-point). |
| ... | int |
z | Z coordinate * 32 (fixed-point). |
| ... | byte |
yRot | Yaw (angle * 256 / 360). |
| ... | byte |
xRot | Pitch (angle * 256 / 360). |
| ... | byte |
yHeadRot | Head yaw (angle * 256 / 360). |
| ... | short |
carriedItem | Item ID of held item. |
| ... | playerUID |
xuid | Player XUID (8 bytes). |
| ... | playerUID |
onlineXuid | Online XUID for splitscreen guests (8 bytes). |
| ... | byte |
playerIndex | Local player index. |
| ... | int |
skinId | Custom skin ID. |
| ... | int |
capeId | Custom cape ID. |
| ... | int |
gamePrivileges | Player game privileges bitfield. |
| ... | metadata |
entityData | Entity metadata (SynchedEntityData). |
Total payload: variable (includes entity metadata).
@subsubsection pkt_23 Packet 23 - AddEntityPacket
Spawn a non-mob entity (minecart, arrow, falling block, etc).
| Offset | Type | Field | Description |
|---|---|---|---|
| 0 | short |
entityId | Entity ID. |
| 2 | byte |
type | Entity type ID (for example 1=boat, 10=minecart, 50=TNT, 60=arrow, 70=falling block). |
| 3 | int |
x | X coordinate * 32 (fixed-point). |
| 7 | int |
y | Y coordinate * 32 (fixed-point). |
| 11 | int |
z | Z coordinate * 32 (fixed-point). |
| 15 | byte |
yRot | Yaw (angle * 256 / 360). |
| 16 | byte |
xRot | Pitch (angle * 256 / 360). |
| 17 | int |
data | Entity-specific data (for example block ID for falling blocks, owner entity ID for projectiles). |
If data is non-zero, three additional velocity fields follow:
| Offset | Type | Field | Description |
|---|---|---|---|
| 21 | short |
xVel | X velocity * 8000. |
| 23 | short |
yVel | Y velocity * 8000. |
| 25 | short |
zVel | Z velocity * 8000. |
Total payload: 21 bytes (no velocity) or 27 bytes (with velocity).
@subsubsection pkt_24 Packet 24 - AddMobPacket
Spawn a mob.
| Offset | Type | Field | Description |
|---|---|---|---|
| 0 | short |
entityId | Entity ID. |
| 2 | byte |
mobType | Mob type ID (for example 50=Creeper, 51=Skeleton, 52=Spider, 54=Zombie, 90=Pig, 91=Sheep). |
| 3 | int |
x | X coordinate * 32 (fixed-point). |
| 7 | int |
y | Y coordinate * 32 (fixed-point). |
| 11 | int |
z | Z coordinate * 32 (fixed-point). |
| 15 | byte |
yRot | Yaw (angle * 256 / 360). |
| 16 | byte |
xRot | Pitch (angle * 256 / 360). |
| 17 | byte |
yHeadRot | Head yaw (angle * 256 / 360). |
| 18 | short |
xVel | X velocity * 8000. |
| 20 | short |
yVel | Y velocity * 8000. |
| 22 | short |
zVel | Z velocity * 8000. |
| 24 | metadata |
entityData | Entity metadata (SynchedEntityData). |
Total payload: 24 bytes + variable metadata.
@subsubsection pkt_26 Packet 26 - AddExperienceOrbPacket
Spawn an XP orb.
| Offset | Type | Field | Description |
|---|---|---|---|
| 0 | int |
entityId | Entity ID. |
| 4 | int |
x | X coordinate * 32 (fixed-point). |
| 8 | int |
y | Y coordinate * 32 (fixed-point). |
| 12 | int |
z | Z coordinate * 32 (fixed-point). |
| 16 | short |
value | XP value of the orb. |
Total payload: 18 bytes.
@subsubsection pkt_28 Packet 28 - SetEntityMotionPacket
Set entity velocity. Has two encoding modes based on a flag bit in the entity ID field.
The first field is a short combining the entity ID and a flag:
- Bits 0-10 (mask
0x07FF): Entity ID (max 2047). - Bit 11 (mask
0x0800): If set, velocity uses 3 bytes (lower precision). If clear, 3 shorts (full precision).
Full precision mode (flag clear):
| Offset | Type | Field | Description |
|---|---|---|---|
| 0 | short |
idAndFlag | Entity ID (low 11 bits), flag=0. |
| 2 | short |
xVel | X velocity * 8000. |
| 4 | short |
yVel | Y velocity * 8000. |
| 6 | short |
zVel | Z velocity * 8000. |
Total payload: 8 bytes.
Compact mode (flag set, bit 11 = 1):
| Offset | Type | Field | Description |
|---|---|---|---|
| 0 | short |
idAndFlag | Entity ID (low 11 bits) OR 0x0800. |
| 2 | byte |
xVel | X velocity / 16 (sign-extended, then multiplied by 16 on read). |
| 3 | byte |
yVel | Y velocity / 16. |
| 4 | byte |
zVel | Z velocity / 16. |
Total payload: 5 bytes. The server automatically picks compact mode when velocity values fit.
@subsubsection pkt_29 Packet 29 - RemoveEntitiesPacket
Despawn one or more entities.
| Offset | Type | Field | Description |
|---|---|---|---|
| 0 | byte |
count | Number of entities to remove. |
| 1 | int[count] |
entityIds | Array of entity IDs (4 bytes each). |
Total payload: 1 + (count * 4) bytes.
@subsubsection pkt_30_33 Packets 30-33 - MoveEntityPacket
Relative entity movement/rotation updates. Four sub-types:
Packet 30 - MoveEntityPacket (base, no movement): short entityId only. Payload: 2 bytes.
Packet 31 - MoveEntityPacket.Pos (position only):
| Offset | Type | Field | Description |
|---|---|---|---|
| 0 | short |
entityId | Entity ID. |
| 2 | byte |
dx | X delta (signed, in 1/32 block units). |
| 3 | byte |
dy | Y delta. |
| 4 | byte |
dz | Z delta. |
Payload: 5 bytes.
Packet 32 - MoveEntityPacket.Rot (rotation only):
| Offset | Type | Field | Description |
|---|---|---|---|
| 0 | short |
entityId | Entity ID. |
| 2 | byte |
yRot | New yaw (angle * 256 / 360). |
| 3 | byte |
xRot | New pitch (angle * 256 / 360). |
Payload: 4 bytes.
Packet 33 - MoveEntityPacket.PosRot (position + rotation):
| Offset | Type | Field | Description |
|---|---|---|---|
| 0 | short |
entityId | Entity ID. |
| 2 | byte |
dx | X delta. |
| 3 | byte |
dy | Y delta. |
| 4 | byte |
dz | Z delta. |
| 5 | byte |
yRot | New yaw. |
| 6 | byte |
xRot | New pitch. |
Payload: 7 bytes.
@subsubsection pkt_34 Packet 34 - TeleportEntityPacket
Teleport an entity to an absolute position.
| Offset | Type | Field | Description |
|---|---|---|---|
| 0 | short |
entityId | Entity ID. |
| 2 | int |
x | X coordinate * 32 (fixed-point). |
| 6 | int |
y | Y coordinate * 32 (fixed-point). |
| 10 | int |
z | Z coordinate * 32 (fixed-point). |
| 14 | byte |
yRot | Yaw (angle * 256 / 360). |
| 15 | byte |
xRot | Pitch (angle * 256 / 360). |
Total payload: 16 bytes.
@subsubsection pkt_35 Packet 35 - RotateHeadPacket
Update an entity's head rotation.
| Offset | Type | Field | Description |
|---|---|---|---|
| 0 | int |
entityId | Entity ID. |
| 4 | byte |
yHeadRot | Head yaw (angle * 256 / 360). |
Total payload: 5 bytes.
@subsubsection pkt_38 Packet 38 - EntityEventPacket
Trigger an entity event (hurt, death, eating, etc).
| Offset | Type | Field | Description |
|---|---|---|---|
| 0 | int |
entityId | Entity ID. |
| 4 | byte |
eventId | Event type (2=hurt, 3=death, 9=eating finished). |
Total payload: 5 bytes.
@subsubsection pkt_39 Packet 39 - SetEntityLinkPacket
Attach or detach entities (leash, riding).
| Offset | Type | Field | Description |
|---|---|---|---|
| 0 | int |
sourceId | Entity being attached (the rider/leashed entity). |
| 4 | int |
destId | Entity being attached to (the vehicle/fence). -1 to detach. |
| 8 | byte |
type | Link type. |
Total payload: 9 bytes.
@subsubsection pkt_40 Packet 40 - SetEntityDataPacket
Update entity metadata. See \ref metadata_encoding "Metadata Encoding" for how to construct the metadata blob.
| Offset | Type | Field | Description |
|---|---|---|---|
| 0 | int |
entityId | Entity ID. |
| 4 | metadata |
data | Packed entity metadata entries. |
Total payload: 4 bytes + variable metadata.
@subsubsection pkt_41 Packet 41 - UpdateMobEffectPacket
Apply or update a potion effect.
| Offset | Type | Field | Description |
|---|---|---|---|
| 0 | int |
entityId | Entity ID. |
| 4 | byte |
effectId | Effect ID (1=speed, 2=slowness, 3=haste, 4=mining fatigue, 5=strength, ...). |
| 5 | byte |
amplifier | Effect level (0 = level I, 1 = level II, etc). |
| 6 | short |
duration | Duration in ticks. |
Total payload: 8 bytes.
@subsubsection pkt_42 Packet 42 - RemoveMobEffectPacket
Remove a potion effect.
| Offset | Type | Field | Description |
|---|---|---|---|
| 0 | int |
entityId | Entity ID. |
| 4 | byte |
effectId | Effect ID to remove. |
Total payload: 5 bytes.
@subsubsection pkt_43 Packet 43 - SetExperiencePacket
Update the XP bar.
| Offset | Type | Field | Description |
|---|---|---|---|
| 0 | float |
progress | XP bar fill amount (0.0-1.0). |
| 4 | short |
level | Current level. |
| 6 | short |
totalXP | Total experience points. |
Total payload: 8 bytes.
@subsubsection pkt_71 Packet 71 - AddGlobalEntityPacket
Spawn a global entity (lightning bolt).
| Offset | Type | Field | Description |
|---|---|---|---|
| 0 | int |
entityId | Entity ID. |
| 4 | byte |
type | Entity type (1 = lightning bolt). |
| 5 | int |
x | X coordinate * 32 (fixed-point). |
| 9 | int |
y | Y coordinate * 32 (fixed-point). |
| 13 | int |
z | Z coordinate * 32 (fixed-point). |
Total payload: 17 bytes.
@subsection packet_ref_player Player Packets
@subsubsection pkt_5 Packet 5 - SetEquippedItemPacket
Change the visible held item for an entity.
| Offset | Type | Field | Description |
|---|---|---|---|
| 0 | int |
entityId | Entity ID. |
| 4 | short |
slot | Equipment slot (0=held). |
| 6 | item |
item | Item data (see \ref item_data "Item Data"). |
Total payload: 6 bytes + item data (2 bytes if empty, 5 bytes if present).
@subsubsection pkt_200 Packet 200 - AwardStatPacket
Award a statistic or achievement.
| Offset | Type | Field | Description |
|---|---|---|---|
| 0 | int |
statId | Statistic/achievement ID. |
| 4 | int |
length | Length of parameter data blob in bytes. |
| 8 | byte[length] |
data | Parameter data (typically a 4-byte int count). |
Total payload: 8 bytes + length bytes. For a simple stat increment, length = 4 and data contains an int count.
@subsubsection pkt_202 Packet 202 - PlayerAbilitiesPacket
Update player abilities.
| Offset | Type | Field | Description |
|---|---|---|---|
| 0 | byte |
flags | Bitfield: 0x01=invulnerable, 0x02=flying, 0x04=canFly, 0x08=instabuild (creative). |
| 1 | float |
flySpeed | Fly speed (default 0.05). |
| 5 | float |
walkSpeed | Walk speed (default 0.1). |
Total payload: 9 bytes.
@subsection packet_ref_container Container Packets
@subsubsection pkt_100 Packet 100 - ContainerOpenPacket
Open a container window.
| Offset | Type | Field | Description |
|---|---|---|---|
| 0 | byte |
containerId | Window ID. |
| 1 | byte |
type | Container type (0=chest, 1=workbench, 2=furnace, 3=dispenser, 4=enchanting table). |
| 2 | byte |
size | Number of slots. |
| 3 | bool |
customName | Whether a custom title follows. |
If type == HORSE (type 12):
| Offset | Type | Field | Description |
|---|---|---|---|
| 4 | int |
entityId | Horse entity ID. |
If customName is true:
| Offset | Type | Field | Description |
|---|---|---|---|
| ... | utf |
title | Custom container title. |
Total payload: 4 bytes minimum, variable with conditionals.
@subsubsection pkt_101 Packet 101 - ContainerClosePacket
Close a container window.
| Offset | Type | Field | Description |
|---|---|---|---|
| 0 | byte |
containerId | Window ID. |
Total payload: 1 byte.
@subsubsection pkt_103 Packet 103 - ContainerSetSlotPacket
Set a single slot in a container.
| Offset | Type | Field | Description |
|---|---|---|---|
| 0 | byte |
containerId | Window ID. |
| 1 | short |
slot | Slot index. |
| 3 | item |
item | Item data (see \ref item_data "Item Data"). |
Total payload: 3 bytes + item data (2 bytes if empty, 5 bytes if present).
@subsubsection pkt_104 Packet 104 - ContainerSetContentPacket
Set all slots in a container.
| Offset | Type | Field | Description |
|---|---|---|---|
| 0 | byte |
containerId | Window ID. |
| 1 | short |
count | Number of item slots. |
| 3 | item[count] |
items | Array of item data entries. |
Total payload: 3 bytes + count * item data.
@subsection packet_ref_all_ids All Packet IDs
Every registered packet. S-C = server to client, C-S = client to server.
Just know that some of these packets have no function (such as scoreboards), most should work.
| ID | Name | S-C | C-S | Notes |
|---|---|---|---|---|
| 0 | KeepAlivePacket | ✓ | ✓ | Connection keepalive. |
| 1 | LoginPacket | ✓ | ✓ | Login handshake. |
| 2 | PreLoginPacket | ✓ | ✓ | Pre-login handshake. |
| 3 | ChatPacket | ✓ | ✓ | Chat messages. |
| 4 | SetTimePacket | ✓ | World time. | |
| 5 | SetEquippedItemPacket | ✓ | Held item display. | |
| 6 | SetSpawnPositionPacket | ✓ | World spawn point. | |
| 7 | InteractPacket | ✓ | Player interact with entity. | |
| 8 | SetHealthPacket | ✓ | Health/food/saturation. | |
| 9 | RespawnPacket | ✓ | ✓ | Respawn/dimension change. |
| 10 | MovePlayerPacket | ✓ | ✓ | Player position (base). |
| 11 | MovePlayerPacket.Pos | ✓ | ✓ | Player position only. |
| 12 | MovePlayerPacket.Rot | ✓ | ✓ | Player rotation only. |
| 13 | MovePlayerPacket.PosRot | ✓ | ✓ | Player position + rotation. |
| 14 | PlayerActionPacket | ✓ | Block breaking, item dropping. | |
| 15 | UseItemPacket | ✓ | Place block / use item. | |
| 16 | SetCarriedItemPacket | ✓ | ✓ | Hotbar slot selection. |
| 17 | EntityActionAtPositionPacket | ✓ | Sleep in bed. | |
| 18 | AnimatePacket | ✓ | ✓ | Entity animations. |
| 19 | PlayerCommandPacket | ✓ | Sneak, sprint, etc. | |
| 20 | AddPlayerPacket | ✓ | Spawn named player. | |
| 22 | TakeItemEntityPacket | ✓ | Item pickup animation. | |
| 23 | AddEntityPacket | ✓ | Spawn non-mob entity. | |
| 24 | AddMobPacket | ✓ | Spawn mob. | |
| 25 | AddPaintingPacket | ✓ | Spawn painting. | |
| 26 | AddExperienceOrbPacket | ✓ | Spawn XP orb. | |
| 27 | PlayerInputPacket | ✓ | Vehicle steering input. | |
| 28 | SetEntityMotionPacket | ✓ | Entity velocity. | |
| 29 | RemoveEntitiesPacket | ✓ | Despawn entities. | |
| 30 | MoveEntityPacket | ✓ | Entity movement (base). | |
| 31 | MoveEntityPacket.Pos | ✓ | Entity position delta. | |
| 32 | MoveEntityPacket.Rot | ✓ | Entity rotation. | |
| 33 | MoveEntityPacket.PosRot | ✓ | Entity pos + rot delta. | |
| 34 | TeleportEntityPacket | ✓ | Entity absolute position. | |
| 35 | RotateHeadPacket | ✓ | Entity head rotation. | |
| 38 | EntityEventPacket | ✓ | Entity events (hurt, death). | |
| 39 | SetEntityLinkPacket | ✓ | Leash / riding. | |
| 40 | SetEntityDataPacket | ✓ | Entity metadata update. | |
| 41 | UpdateMobEffectPacket | ✓ | Apply potion effect. | |
| 42 | RemoveMobEffectPacket | ✓ | Remove potion effect. | |
| 43 | SetExperiencePacket | ✓ | XP bar update. | |
| 44 | UpdateAttributesPacket | ✓ | Entity attributes. | |
| 50 | ChunkVisibilityPacket | ✓ | Chunk visibility. | |
| 51 | BlockRegionUpdatePacket | ✓ | Chunk data. | |
| 52 | ChunkTilesUpdatePacket | ✓ | Multi-block change. | |
| 53 | TileUpdatePacket | ✓ | Single block change. | |
| 54 | TileEventPacket | ✓ | Block action. | |
| 55 | TileDestructionPacket | ✓ | Block breaking animation. | |
| 60 | ExplodePacket | ✓ | Explosion. | |
| 61 | LevelEventPacket | ✓ | World event (sounds, particles). | |
| 62 | LevelSoundPacket | ✓ | Sound effect. | |
| 63 | LevelParticlesPacket | ✓ | Particle effect. | |
| 70 | GameEventPacket | ✓ | Game state change. | |
| 71 | AddGlobalEntityPacket | ✓ | Lightning bolt. | |
| 100 | ContainerOpenPacket | ✓ | Open container. | |
| 101 | ContainerClosePacket | ✓ | ✓ | Close container. |
| 102 | ContainerClickPacket | ✓ | Click container slot. | |
| 103 | ContainerSetSlotPacket | ✓ | ✓ | Set container slot. |
| 104 | ContainerSetContentPacket | ✓ | Set all container slots. | |
| 105 | ContainerSetDataPacket | ✓ | Container progress bar data. | |
| 106 | ContainerAckPacket | ✓ | ✓ | Transaction acknowledgement. |
| 107 | SetCreativeModeSlotPacket | ✓ | ✓ | Creative inventory action. |
| 108 | ContainerButtonClickPacket | ✓ | Enchanting / other button. | |
| 130 | SignUpdatePacket | ✓ | ✓ | Sign text update. |
| 131 | ComplexItemDataPacket | ✓ | Map data. | |
| 132 | TileEntityDataPacket | ✓ | Tile entity NBT data. | |
| 133 | TileEditorOpenPacket | ✓ | Open tile entity editor. | |
| 200 | AwardStatPacket | ✓ | Award statistic. | |
| 201 | PlayerInfoPacket | ✓ | ✓ | Player list info. |
| 202 | PlayerAbilitiesPacket | ✓ | ✓ | Player abilities. |
| 206 | SetObjectivePacket | ✓ | Scoreboard objective. | |
| 207 | SetScorePacket | ✓ | Scoreboard score. | |
| 208 | SetDisplayObjectivePacket | ✓ | Scoreboard display slot. | |
| 209 | SetPlayerTeamPacket | ✓ | Scoreboard team. | |
| 255 | DisconnectPacket | ✓ | ✓ | Disconnect. |
@section where_to_look Where to Look
- \ref Minecraft.Server.FourKit.Experimental.PlayerConnection "PlayerConnection" - Get it via
player.getConnection(). This is what you callsend()on. - \ref Minecraft.Server.FourKit.Sound "Sound" - All sound type IDs for LevelSoundPacket (62). Cast to
intfor the wire value. - \ref Minecraft.Server.FourKit.GameMode "GameMode" - Game mode constants for GameEventPacket (70) and PlayerAbilitiesPacket (202).
- \ref Minecraft.Server.FourKit.Location "Location" - Get world coordinates from
player.getLocation()for position encoding. - Packet source files - The definitive reference is the
write()method of each packet class in thre code (for exampleLevelSoundPacket.cpp,TeleportEntityPacket.cpp).
@section extra-info Extra info
- Packet IDs are a single byte. Only the low byte matters on the wire.
- Position values in entity packets use *32 fixed-point. Sound event positions use *8.
- Rotation angles are a single byte:
(byte)(angle * 256.0 / 360.0). - Velocity is
(short)(velocity * 8000.0), clamped to +/-3.9 blocks/tick before encoding. - Strings use modified UTF-8 with a 2-byte length prefix.
- Item data writes
-1as a short for empty slots (2 bytes), or short ID + byte count + short damage for occupied slots (5 bytes). - The 4-byte size header is written by the server automatically - don't include it in your byte array.
- FourKit's \ref Minecraft.Server.FourKit.Sound "Sound" enum values map directly to the sound IDs used in LevelSoundPacket. VERY USEFUL!!!!
- If you send malformed data, the client will likely disconnect or crash, or do some funny weird stuff. Test carefully.
- Some packets have conditional fields (ExplodePacket, ContainerOpenPacket, SetEntityMotionPacket). Read the wire format tables above carefully.
- Entity metadata - see \ref metadata_encoding "Metadata Encoding" for how to construct SynchedEntityData blobs by hand.