Data Compression

MafiaNet provides several compression techniques to reduce bandwidth usage.

BitStream Compression

WriteCompressed

For integers that are typically small:

// Regular write: always 4 bytes
bs.Write(health);  // int = 4 bytes

// Compressed: 1-5 bytes depending on value
bs.WriteCompressed(health);  // Small values use fewer bytes

// Reading
bs.ReadCompressed(health);

Best for: health, ammo, scores, small counts.

Normalized Vectors

For unit vectors (direction):

// Regular: 12 bytes (3 floats)
bs.Write(dirX);
bs.Write(dirY);
bs.Write(dirZ);

// Compressed: ~6 bytes
bs.WriteNormVector(dirX, dirY, dirZ);

// Reading
bs.ReadNormVector(dirX, dirY, dirZ);

Quaternions

For rotations:

// Regular: 16 bytes (4 floats)
// Compressed: ~6 bytes
bs.WriteNormQuat(w, x, y, z);
bs.ReadNormQuat(w, x, y, z);

Half-Precision Floats

For values where full precision isn’t needed:

// Regular: 4 bytes
// Half precision: 2 bytes
bs.WriteFloat16(value, minValue, maxValue);
bs.ReadFloat16(value, minValue, maxValue);

Integer Ranges

When you know the value’s range:

// Health: 0-100, only needs 7 bits
bs.WriteBitsFromIntegerRange(health, 0, 100);
health = bs.ReadBitsFromIntegerRange(0, 100);

// Team: 0-3, only needs 2 bits
bs.WriteBitsFromIntegerRange(team, 0, 3);

String Compression

Use StringCompressor for repeated strings:

#include "mafianet/StringCompressor.h"

// Add common strings to table
MafiaNet::StringCompressor::Instance()->AddReference(
    "PlayerJoined", 0);
MafiaNet::StringCompressor::Instance()->AddReference(
    "PlayerLeft", 1);

// Encode (uses table index if found)
MafiaNet::StringCompressor::Instance()->EncodeString(
    "PlayerJoined", 256, &bs);

// Decode
char decoded[256];
MafiaNet::StringCompressor::Instance()->DecodeString(
    decoded, 256, &bs);

DataCompressor

For larger data blocks:

#include "mafianet/DataCompressor.h"

// Compress
unsigned compressedSize;
unsigned char* compressed = MafiaNet::DataCompressor::Compress(
    data, dataSize, &compressedSize);

// Decompress
unsigned decompressedSize;
unsigned char* decompressed = MafiaNet::DataCompressor::Decompress(
    compressed, compressedSize, &decompressedSize);

Best Practices

  1. Profile first - Measure actual bandwidth before optimizing

  2. Compress what matters - Focus on frequently sent data

  3. Match precision to needs - Don’t send full floats for position that only needs centimeter precision

  4. Use delta compression - Send only what changed

  5. Batch small messages - Combine multiple small updates

Compression Comparison

Data Type

Uncompressed

Compressed

Savings

int (small)

4 bytes

1-2 bytes

50-75%

Normalized vector

12 bytes

6 bytes

50%

Quaternion

16 bytes

6 bytes

62%

Float (range known)

4 bytes

2 bytes

50%

See Also