Programming Tips¶
This guide provides best practices and tips for effective MafiaNet development.
Connection Management¶
Always handle all disconnect scenarios:
switch (packet->data[0]) {
case ID_DISCONNECTION_NOTIFICATION:
// Clean disconnect - save player data
SavePlayerData(packet->guid);
RemovePlayer(packet->guid);
break;
case ID_CONNECTION_LOST:
// Timeout - may need reconnection logic
MarkPlayerDisconnected(packet->guid);
StartReconnectionTimer(packet->guid);
break;
}
Don’t forget to deallocate packets:
// BAD - memory leak
MafiaNet::Packet* p = peer->Receive();
if (p->data[0] == ID_SOMETHING) { return; }
// GOOD - always deallocate
MafiaNet::Packet* p = peer->Receive();
if (p) {
ProcessPacket(p);
peer->DeallocatePacket(p);
}
BitStream Best Practices¶
Use appropriate data types:
// BAD - wastes bandwidth
bs.Write((int)health); // 32 bits for 0-100 value
// GOOD - right-sized
bs.Write((unsigned char)health); // 8 bits
// BETTER - even smaller
bs.WriteBits((unsigned char*)&health, 7); // 7 bits for 0-127
Reset BitStream read position for re-reading:
MafiaNet::BitStream bs(packet->data, packet->length, false);
bs.IgnoreBytes(1); // Skip message ID
// Read once
int value1;
bs.Read(value1);
// Reset to read again
bs.ResetReadPointer();
bs.IgnoreBytes(1);
Serialize in consistent order:
// Write order MUST match read order
void WritePlayer(BitStream& bs, Player& p) {
bs.Write(p.id);
bs.Write(p.x);
bs.Write(p.y);
bs.Write(p.health);
}
void ReadPlayer(BitStream& bs, Player& p) {
bs.Read(p.id);
bs.Read(p.x);
bs.Read(p.y);
bs.Read(p.health);
}
Reliability Selection¶
Choose the right reliability for each message type:
Data Type |
Reliability |
Why |
|---|---|---|
Position updates |
UNRELIABLE_SEQUENCED |
Latest matters most |
Health changes |
RELIABLE |
Must arrive |
Chat messages |
RELIABLE_ORDERED |
Order matters |
Spawn events |
RELIABLE_ORDERED |
Critical + ordered |
Input commands |
UNRELIABLE_SEQUENCED |
Stale input useless |
Plugin Architecture¶
Order matters for plugin attachment:
// Plugins process packets in attachment order
peer->AttachPlugin(&authPlugin); // First: authenticate
peer->AttachPlugin(&messageFilter); // Second: filter
peer->AttachPlugin(&gamePlugin); // Third: game logic
Use plugin callbacks appropriately:
class MyPlugin : public MafiaNet::PluginInterface2 {
// Called before packet reaches application
PluginReceiveResult OnReceive(Packet* packet) override {
if (ShouldHandlePacket(packet)) {
// RR_STOP_PROCESSING_AND_DEALLOCATE - handled, stop
// RR_CONTINUE_PROCESSING - let others see it
// RR_STOP_PROCESSING - handled, don't deallocate
}
return RR_CONTINUE_PROCESSING;
}
};
Performance Tips¶
Batch sends when possible:
// Instead of many small sends
for (auto& update : updates) {
peer->Send(&update, ...); // Many syscalls
}
// Combine into one BitStream
MafiaNet::BitStream bs;
bs.Write((MafiaNet::MessageID)ID_BATCH_UPDATE);
bs.Write((unsigned short)updates.size());
for (auto& update : updates) {
update.Serialize(bs);
}
peer->Send(&bs, ...); // One syscall
Use ordering channels wisely:
// Different channels don't block each other
peer->Send(&positionData, MED, RELIABLE_ORDERED, 0, ...); // Channel 0
peer->Send(&chatMessage, MED, RELIABLE_ORDERED, 1, ...); // Channel 1
// Chat won't wait for position packets
Debugging Tips¶
Enable PacketLogger during development
Use GetStatistics() to monitor connection health
Log all connection state changes
Test with artificial latency and packet loss
See Also¶
Frequently Asked Questions - Common questions
Congestion Control - Bandwidth management
Debugging Disconnects - Troubleshooting