Biblioteca

Anti-AFK

Detecte jogadores parados por movimento e por chat, com 12 s de tolerância.

O anti-AFK marca como AFK um jogador que ficou 12 segundos sem se mexer e sem falar no chat. Qualquer um dos dois sinais zera o relógio.

ts
room.enableAntiAfk();                                  // padrão: 12 s

room.on('player-afk',  (id) => room.kickPlayer(id));   // uma vez, quando vira AFK
room.on('player-back', (id) => room.chat(`jogador ${id} voltou`));

room.isAfk(playerId);                                  // consulta pontual
room.disableAntiAfk();

Opções

ts
room.enableAntiAfk({
  thresholdMs: 12_000,     // tempo parado até virar AFK
  checkIntervalMs: 1_000,  // frequência da checagem
});

O tempo padrão também está disponível como a constante AFK_THRESHOLD_MS.

Quem é vigiado

Só jogadores em um time durante uma partida. Espectadores e o próprio bot são ignorados. O relógio começa quando a partida começa (ou quando o jogador entra em um time durante a partida) e é descartado quando a partida termina.

De onde vêm os sinais

SinalOrigemEvento
ChatSocket.IOchat-message
MovimentoWebRTC (frames de input entre os peers)peer-input

O movimento não passa pelo Socket.IO: os jogadores trocam frames de input entre si por WebRTC. A biblioteca completa o handshake WebRTC como se fosse um jogador e recebe esses frames. Ela manda um frame por tecla apertada ou solta, e nenhum enquanto o jogador está parado, o que torna a detecção confiável.

peer-input entrega { playerId, peerID, data }, com o frame já associado ao jogador certo. Você pode usá-lo diretamente para estatísticas de atividade.

Limitações importantes

  • Precisa do modo real. O evento peer-input só existe quando a sala usa o transporte real (com peerID), como em createRoom() e joinRoom(). Em testes com transporte falso, emita peer-input manualmente.
  • Confiabilidade do sinal. Se por algum motivo nenhum frame de movimento chegar durante uma partida inteira, o sinal não é confiável. A sala 24/7 ignora o AFK automático nesse caso, para nunca punir todos por uma falha de rede. Faça o mesmo se você aplicar punições.

Exemplo completo

ts
import type { BonkRoom } from 'bonktools';

export function setupAntiAfk(room: BonkRoom): void {
  room.enableAntiAfk();

  const name = (id: number) => room.state.players.get(id)?.userName ?? `#${id}`;

  room.on('player-afk', (id) => {
    room.chat(`${name(id)} está AFK!`);
    room.kickPlayer(id); // remova esta linha se só quiser avisar
  });

  room.on('player-back', (id) => room.chat(`${name(id)} voltou.`));
}