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.
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
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
| Sinal | Origem | Evento |
|---|---|---|
| Chat | Socket.IO | chat-message |
| Movimento | WebRTC (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-inputsó existe quando a sala usa o transporte real (compeerID), como emcreateRoom()ejoinRoom(). Em testes com transporte falso, emitapeer-inputmanualmente. - 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
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.`));
}