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

LayerTechnology
TransportWebSocket (TLS)
Engine.IOversion 3 (EIO=3)
Socket.IOversion 2
Framing42[eventId, payload]
SerializationJSON

Flow of a session

  1. Login at login_legacy.php, which returns a token.
  2. Server discovery (getrooms.php to create, autojoin.php to join by URL).
  3. Socket.IO connection to the indicated server, with periodic timesync.
  4. Create (CREATE_ROOM) or join (JOIN_ROOM) the room.
  5. The host answers every joining player with the initial data (see below).
  6. Match: the host sends TRIGGER_START and the server echoes GAME_START to 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:

SituationPacket
LobbyINFORM_IN_LOBBY (out 11)
Match in progressINFORM_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 are null.
  • The room creator doesn't receive JOIN_ROOM. They are player 0 and host.
  • room_full is ambiguous. It is only terminal when the bot hasn't joined the room yet.
  • The map in INFORM_IN_LOBBY is a JSON object, not an LZ string.
  • The IS blob depends on the number of players and on the map.
  • Explicit bal. With bal: [], non-contiguous ids can produce swapped spawns.
  • gs.tl must reflect the room's real lock: with the lock on and gs.tl: false, players were frozen.
  • Packet ids have separate namespaces per direction (the incoming 20 is chat; the outgoing 20 is 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.