Reference
The bonk.io protocol
A summary of the protocol the library speaks, with the most important pitfalls.
This page summarizes what the library does under the hood. The complete documentation, with every packet ID and format, is in the repository's BONK_PROTOCOL.md file.
Network layers
| Layer | Technology |
|---|---|
| Transport | WebSocket (TLS) |
| Engine.IO | version 3 (EIO=3) |
| Socket.IO | version 2 |
| Framing | 42[eventId, payload] |
| Serialization | JSON |
Flow of a session
- Login at
login_legacy.php, which returns a token. - Server discovery (
getrooms.phpto create,autojoin.phpto join by URL). - Socket.IO connection to the indicated server, with periodic timesync.
- Create (
CREATE_ROOM) or join (JOIN_ROOM) the room. - The host answers every joining player with the initial data (see below).
- Match: the host sends
TRIGGER_STARTand the server echoesGAME_STARTto everyone.
Two connections: Socket.IO and WebRTC
Socket.IO covers the room (players, teams, chat, match start and end). But player movement inside the match does not go through it: it is synchronized by WebRTC between peers, signaled by a standard PeerJS broker. To receive those frames (the basis of anti-AFK), the library completes the WebRTC handshake as an ordinary player.
Input frames are small binary packets. There is one frame per key pressed or released and none while the player is idle.
Initial data for joiners
When a player joins, the host sends one packet with the room state. The client only accepts the first:
| Situation | Packet |
|---|---|
| Lobby | INFORM_IN_LOBBY (out 11) |
| Match in progress | INFORM_IN_GAME (out 40), with state, stateID, fc, inputs, admin, gs, random |
Sending both makes the second one ignored. The library picks the right one automatically.
Pitfalls the library already handles
players[]is a sparse array. The index is the player id; vacant slots arenull.- The room creator doesn't receive
JOIN_ROOM. They are player 0 and host. room_fullis ambiguous. It is only terminal when the bot hasn't joined the room yet.- The map in
INFORM_IN_LOBBYis a JSON object, not an LZ string. - The IS blob depends on the number of players and on the map.
- Explicit
bal. Withbal: [], non-contiguous ids can produce swapped spawns. gs.tlmust reflect the room's real lock: with the lock on andgs.tl: false, players were frozen.- Packet ids have separate namespaces per direction (the incoming
20is chat; the outgoing20is something else).
Team numbering
0 spec · 1 FFA · 2 red · 3 blue · 4 green · 5 yellow.
Rate limits
The server limits how often several commands can be sent and answers with a status-message (rate_limit_tl for the team lock, rate_limit_cot for team changes, etc.). Terminal codes, such as banned, end the room.