DocumentationCore Protocol

Encoding & Wire Format

PaindaProtocol is built to minimize serialization overhead and bandwidth usage. It uses a custom Binary layout to achieve 70-90% smaller payloads compared to standard JSON WebSockets.

The Binary Frame (v2)

Instead of passing raw JSON strings natively over WebSockets, Painda encodes every message into a strict Binary Frame starting with a 16-byte header:

BytesFieldDescription
0-3Magic Bytes0x50504E44 ("PPND") - Identifies a valid Painda frame.
4-5Version (uint16)Wire protocol version (currently 2).
6-7Flags (uint16)Bits 0-1 mode, Bit 2 compression, Bit 3 custom schema encoding.
8-11Length (uint32)Length of the following payload array.
12-13Type ID (uint16)0 = JSON fallback, >0 = Custom Schema ID.
14-15Reserved (uint16)Reserved for future expansion.
16+PayloadThe encoded message bytes.

Fallback: JSON mode

By default, if you don't define a custom schema, PaindaProtocol uses JSON encoding wrapped inside the binary frame. This means the header routing is hyper-fast, but the payload itself is standard TextEncoder().encode(JSON.stringify(msg)). This provides perfect Developer Experience (DX) for modern apps without writing schemas.

Custom Schemas (Maximum Speed)

For high-frequency game packets (like player movement), JSON is too bloated. PaindaProtocol allows you to register custom binary schemas using the PPSchemaRegistry.

const { PPSchemaRegistry, structSerializer } = require("@painda/core/schema");

// 1. Create a registry
const registry = new PPSchemaRegistry();

// 2. Register your high-freq payload
registry.register("player_move", 1, structSerializer([
  { name: "x", type: "float32" },
  { name: "y", type: "float32" }
]));

// Now { type: "player_move", payload: { x: 10.5, y: -4.2 } }
// is encoded into exactly 8 bytes of payload instead of ~50 bytes of JSON!

Compression Support

If your payload exceeds the compression threshold, the server automatically compresses it using Zlib/Deflate (for Node.js) and sets the `FLAG_COMPRESSED` bit. Browser clients decompress this seamlessly using the Native Web DecompressionStream API.