Receiving Packets

Receive packets by polling Receive() in your game loop.

The Receive Loop

MafiaNet::Packet* packet;
for (packet = peer->Receive(); packet;
     peer->DeallocatePacket(packet), packet = peer->Receive()) {

    // Process packet
    ProcessPacket(packet);
}

Warning

Always call DeallocatePacket() after processing. Failure to do so causes memory leaks.

The Packet Structure

struct Packet {
    SystemAddress systemAddress;  // Sender's address
    RakNetGUID guid;              // Sender's unique ID
    unsigned int length;          // Data length in bytes
    BitSize_t bitSize;            // Data length in bits
    unsigned char* data;          // The actual data
};
  • systemAddress - IP:port of the sender

  • guid - Unique identifier of the sender (survives reconnects)

  • data[0] - Always the message ID

Processing Messages

void ProcessPacket(MafiaNet::Packet* packet) {
    switch (packet->data[0]) {
        // System messages
        case ID_CONNECTION_REQUEST_ACCEPTED:
            OnConnected(packet);
            break;
        case ID_NEW_INCOMING_CONNECTION:
            OnClientConnected(packet);
            break;
        case ID_DISCONNECTION_NOTIFICATION:
        case ID_CONNECTION_LOST:
            OnDisconnected(packet);
            break;

        // Custom messages
        default:
            if (packet->data[0] >= ID_USER_PACKET_ENUM) {
                OnGameMessage(packet);
            }
            break;
    }
}

Reading Packet Data

Using BitStream

void OnGameMessage(MafiaNet::Packet* packet) {
    MafiaNet::BitStream bs(packet->data, packet->length, false);

    MafiaNet::MessageID msgId;
    bs.Read(msgId);

    switch (msgId) {
        case ID_PLAYER_POSITION: {
            float x, y, z;
            bs.Read(x);
            bs.Read(y);
            bs.Read(z);
            UpdatePlayerPosition(packet->guid, x, y, z);
            break;
        }
        case ID_CHAT_MESSAGE: {
            MafiaNet::RakString message;
            bs.Read(message);
            DisplayChatMessage(packet->guid, message);
            break;
        }
    }
}

Using Struct Cast

#pragma pack(push, 1)
struct PlayerPositionPacket {
    unsigned char msgId;
    float x, y, z;
};
#pragma pack(pop)

case ID_PLAYER_POSITION: {
    PlayerPositionPacket* pos = (PlayerPositionPacket*)packet->data;
    UpdatePlayerPosition(packet->guid, pos->x, pos->y, pos->z);
    break;
}

Handling Timestamps

If a packet starts with ID_TIMESTAMP:

MafiaNet::BitStream bs(packet->data, packet->length, false);

MafiaNet::MessageID firstByte;
bs.Read(firstByte);

MafiaNet::Time timestamp = 0;
if (firstByte == ID_TIMESTAMP) {
    bs.Read(timestamp);
    bs.Read(firstByte);  // Now read actual message ID
}

// timestamp is in your local time (auto-converted by MafiaNet)
MafiaNet::Time packetAge = MafiaNet::GetTime() - timestamp;

System Message Reference

Message ID

When Received

ID_CONNECTION_REQUEST_ACCEPTED

Connected to server (client)

ID_NEW_INCOMING_CONNECTION

Client connected (server)

ID_DISCONNECTION_NOTIFICATION

Clean disconnect

ID_CONNECTION_LOST

Connection timed out

ID_CONNECTION_ATTEMPT_FAILED

Could not connect

ID_NO_FREE_INCOMING_CONNECTIONS

Server is full

ID_INVALID_PASSWORD

Wrong password

ID_ALREADY_CONNECTED

Already connected to this peer

ID_UNCONNECTED_PING

Offline ping received

ID_UNCONNECTED_PONG

Offline ping response

Validation

Always validate packet data:

// Check minimum length
if (packet->length < sizeof(PlayerPositionPacket)) {
    printf("Malformed packet from %s\n",
           packet->systemAddress.ToString());
    return;
}

// Check read success
if (!bs.Read(x) || !bs.Read(y) || !bs.Read(z)) {
    printf("Failed to read position data\n");
    return;
}

// Validate values
if (!IsValidPosition(x, y, z)) {
    printf("Invalid position from %s\n",
           packet->systemAddress.ToString());
    return;
}

Thread Safety

Receive() is thread-safe. You can call it from any thread, but typically it’s called from your main game loop.

For background processing:

// In a network thread
while (running) {
    MafiaNet::Packet* packet = peer->Receive();
    if (packet) {
        // Queue for main thread processing
        packetQueue.Push(packet);
    } else {
        Sleep(1);
    }
}

// In main thread
MafiaNet::Packet* packet;
while (packetQueue.Pop(packet)) {
    ProcessPacket(packet);
    peer->DeallocatePacket(packet);
}

See Also