Skip to main content

Overview

The packet system handles all network communication between clients and servers. Each packet type represents a specific message or event in the game protocol.

Base Packet Class

class Packet
Location: Minecraft.World/Packet.h

Core Methods

All packets must implement these virtual methods:
virtual int getId() = 0;                          // Unique packet ID
virtual void read(DataInputStream *dis) = 0;      // Deserialize from stream
virtual void write(DataOutputStream *dos) = 0;    // Serialize to stream
virtual void handle(PacketListener *listener) = 0; // Process packet
virtual int getEstimatedSize() = 0;               // Size in bytes

Packet Registration

static void map(int id, bool receiveOnClient, bool receiveOnServer, 
                bool sendToAnyClient, bool renderStats, 
                const type_info& clazz, packetCreateFn)
Registers a packet type with the protocol. Each packet has:
  • Unique ID number
  • Direction flags (client/server)
  • Factory function for creation

Packet I/O

Reading Packets

static shared_ptr<Packet> readPacket(DataInputStream *dis, bool isServer)
Reads a packet from the network stream.

Writing Packets

static void writePacket(shared_ptr<Packet> packet, DataOutputStream *dos)
Writes a packet to the network stream.

Connection Packets

LoginPacket (ID: 1)

Establishes a player connection to the server.
class LoginPacket : public Packet
Location: Minecraft.World/LoginPacket.h

Fields

int clientVersion;              // Protocol version
wstring userName;               // Player name
__int64 seed;                   // World seed
char dimension;                 // 0=Overworld, -1=Nether, 1=End
char difficulty;                // 0=Peaceful, 1=Easy, 2=Normal, 3=Hard
int gameType;                   // 0=Survival, 1=Creative, 2=Adventure
BYTE mapHeight;                 // Maximum build height
BYTE maxPlayers;                // Server player capacity
PlayerUID m_offlineXuid;        // Offline player ID
PlayerUID m_onlineXuid;         // Online player ID
LevelType *m_pLevelType;        // World type

Constructors

Client to Server:
LoginPacket(const wstring& userName, int clientVersion, 
            PlayerUID offlineXuid, PlayerUID onlineXuid, 
            bool friendsOnlyUGC, DWORD ugcPlayersVersion,
            DWORD skinId, DWORD capeId, bool isGuest)
Server to Client:
LoginPacket(const wstring& userName, int clientVersion, 
            LevelType *pLevelType, __int64 seed, int gameType,
            char dimension, BYTE mapHeight, BYTE maxPlayers, 
            char difficulty, INT multiplayerInstanceId, 
            BYTE playerIndex, bool newSeaLevel, 
            unsigned int uiGamePrivileges, int xzSize, int hellScale)

Example Usage

// Client sends login request
auto loginPacket = make_shared<LoginPacket>(
    playerName,
    PROTOCOL_VERSION,
    offlineXuid,
    onlineXuid,
    false,  // friendsOnlyUGC
    0,      // ugcPlayersVersion
    skinId,
    capeId,
    false   // isGuest
);
connection->send(loginPacket);

DisconnectPacket (ID: 255)

Notifies of connection termination.
class DisconnectPacket : public Packet
Location: Minecraft.World/DisconnectPacket.h

Disconnect Reasons

enum eDisconnectReason
{
    eDisconnect_None = 0,
    eDisconnect_Quitting,               // Player chose to quit
    eDisconnect_Closed,                 // Normal close
    eDisconnect_LoginTooLong,           // Login timeout
    eDisconnect_IllegalStance,          // Invalid position
    eDisconnect_IllegalPosition,        // Invalid coordinates
    eDisconnect_MovedTooQuickly,        // Anti-cheat trigger
    eDisconnect_NoFlying,               // Flying not allowed
    eDisconnect_Kicked,                 // Kicked by admin
    eDisconnect_TimeOut,                // Network timeout
    eDisconnect_Overflow,               // Buffer overflow
    eDisconnect_EndOfStream,            // Connection lost
    eDisconnect_ServerFull,             // Max players reached
    eDisconnect_OutdatedServer,         // Version mismatch
    eDisconnect_OutdatedClient,         // Version mismatch
    eDisconnect_UnexpectedPacket,       // Protocol error
    eDisconnect_ConnectionCreationFailed, // Socket error
    eDisconnect_NoMultiplayerPrivilegesHost, // No permission
    eDisconnect_NoMultiplayerPrivilegesJoin, // No permission
    eDisconnect_Banned                  // Player banned
};

Fields

eDisconnectReason reason;  // Why connection closed

Example Usage

// Server kicks player
auto disconnectPacket = make_shared<DisconnectPacket>(
    DisconnectPacket::eDisconnect_Kicked
);
playerConnection->send(disconnectPacket);

PreLoginPacket

Initiates the connection handshake before login. Location: Minecraft.World/PreLoginPacket.h

Entity Packets

AddEntityPacket (ID: 23)

Spawns a non-living entity in the world.
class AddEntityPacket : public Packet
Location: Minecraft.World/AddEntityPacket.h

Entity Types

static const int BOAT = 1;
static const int ITEM = 2;
static const int MINECART_RIDEABLE = 10;
static const int MINECART_CHEST = 11;
static const int MINECART_FURNACE = 12;
static const int PRIMED_TNT = 50;
static const int ENDER_CRYSTAL = 51;
static const int ARROW = 60;
static const int SNOWBALL = 61;
static const int EGG = 62;
static const int FIREBALL = 63;
static const int SMALL_FIREBALL = 64;
static const int THROWN_ENDERPEARL = 65;
static const int FALLING = 70;
static const int ITEM_FRAME = 71;
static const int EYEOFENDERSIGNAL = 72;
static const int THROWN_POTION = 73;
static const int THROWN_EXPBOTTLE = 75;
static const int FISH_HOOK = 90;
static const int DRAGON_FIRE_BALL = 200;

Fields

int id;              // Entity ID
int x, y, z;         // Position (fixed-point, divide by 32)
int xa, ya, za;      // Velocity (divide by 8000)
int type;            // Entity type constant
int data;            // Type-specific data
byte yRot, xRot;     // Rotation (multiply by 360/256)

Constructors

AddEntityPacket(shared_ptr<Entity> e, int type, int yRotp, int xRotp,
                int xp, int yp, int zp)

AddEntityPacket(shared_ptr<Entity> e, int type, int data, 
                int yRotp, int xRotp, int xp, int yp, int zp)

Example Usage

// Spawn a snowball
auto entity = make_shared<Snowball>(level, x, y, z);
auto packet = make_shared<AddEntityPacket>(
    entity,
    AddEntityPacket::SNOWBALL,
    yRot, xRot,
    x * 32, y * 32, z * 32
);
serverConnection->sendToAll(packet);

AddPlayerPacket

Adds a player entity to the world. Location: Minecraft.World/AddPlayerPacket.h

Fields

int id;                        // Entity ID
wstring name;                  // Player name
PlayerUID xuid;                // Player unique ID
int x, y, z;                   // Position (fixed-point)
byte yRot, xRot, yHeadRot;     // Rotation
int carriedItem;               // Held item ID
BYTE m_playerIndex;            // Player index (0-3)
DWORD m_skinId, m_capeId;      // Customization IDs
unsigned int m_uiGamePrivileges; // Permission flags

AddMobPacket

Spawns a mob (living entity) in the world. Location: Minecraft.World/AddMobPacket.h

RemoveEntitiesPacket

Removes one or more entities from the world. Location: Minecraft.World/RemoveEntitiesPacket.h

Fields

int *ids;      // Array of entity IDs
int length;    // Number of entities

AddExperienceOrbPacket

Spawns an experience orb. Location: Minecraft.World/AddExperienceOrbPacket.h

Movement Packets

MovePlayerPacket (ID: 10-13)

Updates player position and rotation.
class MovePlayerPacket : public Packet
Location: Minecraft.World/MovePlayerPacket.h

Fields

double x, y, z, yView;  // Position coordinates
float yRot, xRot;       // Rotation angles
bool onGround;          // Grounded flag
bool hasPos, hasRot;    // Which fields are present
bool isFlying;          // Flying state

Variants

PosRot (ID: 13) - Position and rotation
MovePlayerPacket::PosRot(double x, double y, double yView, double z,
                         float yRot, float xRot, bool onGround, bool isFlying)
Pos (ID: 11) - Position only
MovePlayerPacket::Pos(double x, double y, double yView, double z,
                      bool onGround, bool isFlying)
Rot (ID: 12) - Rotation only
MovePlayerPacket::Rot(float yRot, float xRot, bool onGround, bool isFlying)

Example Usage

// Send full position update
auto packet = make_shared<MovePlayerPacket::PosRot>(
    player->x, player->y, player->yView, player->z,
    player->yRot, player->xRot,
    player->onGround, player->isFlying
);
connection->send(packet);

TeleportEntityPacket

Instantly moves an entity to a new position. Location: Minecraft.World/TeleportEntityPacket.h

MoveEntityPacket

Applies relative movement to an entity. Location: Minecraft.World/MoveEntityPacket.h

SetEntityMotionPacket

Sets an entity’s velocity. Location: Minecraft.World/SetEntityMotionPacket.h

World Packets

TileUpdatePacket

Updates a single block in the world. Location: Minecraft.World/TileUpdatePacket.h

Fields

int x, y, z;       // Block position
int block;         // Block type ID
int data;          // Block metadata
int levelIdx;      // Dimension index

ChunkTilesUpdatePacket

Updates multiple blocks within a chunk. Location: Minecraft.World/ChunkTilesUpdatePacket.h

Fields

int xc, zc;         // Chunk coordinates
short *positions;   // Packed block positions
byte *blocks;       // Block IDs
byte *data;         // Block metadata
int count;          // Number of blocks
int levelIdx;       // Dimension index

BlockRegionUpdatePacket

Updates a rectangular region of blocks. Location: Minecraft.World/BlockRegionUpdatePacket.h

ChunkVisibilityPacket

Controls which chunks are loaded on the client. Location: Minecraft.World/ChunkVisibilityPacket.h

Fields

int x, z;          // Chunk coordinates
bool visible;      // Load or unload chunk

ChunkVisibilityAreaPacket

Sets visibility for a rectangular area of chunks. Location: Minecraft.World/ChunkVisibilityAreaPacket.h

Gameplay Packets

ChatPacket (ID: 3)

Sends chat messages and game notifications.
class ChatPacket : public Packet
Location: Minecraft.World/ChatPacket.h

Message Types

enum EChatPacketMessage
{
    e_ChatCustom = 0,              // Custom text message
    e_ChatBedOccupied,             // Bed is occupied
    e_ChatBedNoSleep,              // Can't sleep now
    e_ChatPlayerJoinedGame,        // Player joined
    e_ChatPlayerLeftGame,          // Player left
    e_ChatPlayerKickedFromGame,    // Player kicked
    e_ChatDeathInFire,             // Death message
    e_ChatDeathDrown,              // Death message
    e_ChatDeathFall,               // Death message
    // ... many more localized messages
};

Fields

vector<wstring> m_stringArgs;      // String parameters
vector<int> m_intArgs;             // Integer parameters  
EChatPacketMessage m_messageType;  // Message type

Example Usage

// Custom chat message
auto chatPacket = make_shared<ChatPacket>(
    L"Hello, world!",
    ChatPacket::e_ChatCustom
);

// Localized death message
auto deathPacket = make_shared<ChatPacket>(
    playerName,
    ChatPacket::e_ChatDeathFall
);
deathPacket->m_stringArgs.push_back(playerName);

SetHealthPacket

Updates player health and food. Location: Minecraft.World/SetHealthPacket.h

SetExperiencePacket

Updates player experience and level. Location: Minecraft.World/SetExperiencePacket.h

RespawnPacket

Respawns the player after death. Location: Minecraft.World/RespawnPacket.h

SetSpawnPositionPacket

Sets the world spawn point. Location: Minecraft.World/SetSpawnPositionPacket.h

SetTimePacket

Synchronizes world time. Location: Minecraft.World/SetTimePacket.h

Inventory Packets

ContainerSetContentPacket

Sets all slots in a container. Location: Minecraft.World/ContainerSetContentPacket.h

ContainerSetSlotPacket

Updates a single inventory slot. Location: Minecraft.World/ContainerSetSlotPacket.h

ContainerClickPacket

Handles inventory click interactions. Location: Minecraft.World/ContainerClickPacket.h

SetCarriedItemPacket

Changes the held hotbar slot. Location: Minecraft.World/SetCarriedItemPacket.h

Packet Serialization

Writing Data

virtual void write(DataOutputStream *dos)
{
    dos->writeInt(entityId);
    dos->writeDouble(x);
    dos->writeDouble(y);
    dos->writeDouble(z);
    dos->writeByte(yRot);
    dos->writeByte(xRot);
}

Reading Data

virtual void read(DataInputStream *dis)
{
    entityId = dis->readInt();
    x = dis->readDouble();
    y = dis->readDouble();
    z = dis->readDouble();
    yRot = dis->readByte();
    xRot = dis->readByte();
}

Utility Methods

// String I/O
static void writeUtf(const wstring& value, DataOutputStream *dos);
static wstring readUtf(DataInputStream *dis, int maxLength);

// Item I/O
static shared_ptr<ItemInstance> readItem(DataInputStream *dis);
static void writeItem(shared_ptr<ItemInstance> item, DataOutputStream *dos);

// NBT I/O
static CompoundTag *readNbt(DataInputStream *dis);
static void writeNbt(CompoundTag *tag, DataOutputStream *dos);

Creating Custom Packets

Step 1: Define Packet Class

class MyCustomPacket : public Packet, public enable_shared_from_this<MyCustomPacket>
{
public:
    int myData;
    wstring myString;
    
    MyCustomPacket() {}
    MyCustomPacket(int data, const wstring& str) 
        : myData(data), myString(str) {}
    
    virtual int getId() { return 250; } // Choose unused ID
    
    virtual void read(DataInputStream *dis) {
        myData = dis->readInt();
        myString = Packet::readUtf(dis, 256);
    }
    
    virtual void write(DataOutputStream *dos) {
        dos->writeInt(myData);
        Packet::writeUtf(myString, dos);
    }
    
    virtual void handle(PacketListener *listener) {
        // Cast to your listener interface
        // listener->handleMyCustomPacket(shared_from_this());
    }
    
    virtual int getEstimatedSize() {
        return 4 + myString.length() * 2;
    }
    
    static shared_ptr<Packet> create() {
        return shared_ptr<Packet>(new MyCustomPacket());
    }
};

Step 2: Register Packet

// In Packet::staticCtor()
Packet::map(
    250,                     // Packet ID
    true,                    // Receive on client
    true,                    // Receive on server
    false,                   // Send to any client
    false,                   // Render stats
    typeid(MyCustomPacket),  // Type info
    &MyCustomPacket::create  // Factory function
);

Step 3: Add Handler

// Add to PacketListener interface
virtual void handleMyCustomPacket(shared_ptr<MyCustomPacket> packet) {}

// Implement in ClientConnection or PlayerConnection
void handleMyCustomPacket(shared_ptr<MyCustomPacket> packet) {
    // Process packet
    int data = packet->myData;
    wstring str = packet->myString;
}

Packet Optimization

Invalidation

Some packets can be replaced by newer versions:
virtual bool canBeInvalidated() { return true; }

virtual bool isInvalidatedBy(shared_ptr<Packet> packet) {
    // Return true if 'packet' supersedes this one
    auto other = dynamic_pointer_cast<MovePlayerPacket>(packet);
    return other != nullptr;
}

Async Processing

virtual bool isAsync() { return true; }  // Can process on network thread

Packet Statistics

The packet system tracks bandwidth usage:
static void recordOutgoingPacket(shared_ptr<Packet> packet);
static void renderPacketStats(int id);
static void renderAllPacketStats();
Enable with PACKET_ENABLE_STAT_TRACKING define.

Best Practices

  1. Always validate packet data - Check bounds and validity
  2. Keep packets small - Minimize bandwidth usage
  3. Use batch packets when possible (ChunkTilesUpdate vs individual TileUpdate)
  4. Handle missing entities gracefully - Entity may have despawned
  5. Version your protocol - Use clientVersion field for compatibility
  6. Test packet order - Network may reorder packets
  7. Implement getEstimatedSize() accurately for bandwidth tracking

See Also

Build docs developers (and LLMs) love