Checkers — AFK timeout
The AFK system prevents games from stalling when a player goes idle. Each player has 90 seconds to make a move. The timer resets on every move — it only counts idle time, not total game time.
Timeline
| At | Event | Payload | What to do |
|---|---|---|---|
| 0s | (move made) | — | AFK timer resets to 0. |
| 60s idle | checkers:afk_warning | { playerId, secondsRemaining: 30 } | Show a countdown banner. If playerId === your playerId, you'll forfeit in 30s. |
| any move | checkers:afk_warning_cleared | {} | Dismiss the banner immediately. |
| 90s idle | game:over | { winner: opponentId, reason: "afk_timeout" } | Idle player is forfeited. Opponent wins. |
checkers:afk_warning — field reference
| Field | Type | Description |
|---|---|---|
playerId | string | The player who is idle. Compare to your own playerId to know if it's you or the opponent. |
secondsRemaining | number | Seconds until forfeit. Starts at 30. The event fires once — you must count down locally. |
Disabling AFK timeout
// Option A — server-side (session creation)
body: JSON.stringify({ game: 'checkers', afkTimeoutEnabled: false, … })
// Option B — client-side (matchmaking:join)
socket.emit('matchmaking:join', { username: 'Alex', afkTimeoutEnabled: false })Banner implementation
The server fires checkers:afk_warning once with secondsRemaining: 30. Run a local countdown interval to update the UI each second.
import { useState, useEffect, useRef } from 'react';
import { useSocket } from '@beta-gamer/react';
function AfkBanner({ myPlayerId }: { myPlayerId: string }) {
const socket = useSocket();
const [warning, setWarning] = useState<{ isSelf: boolean; seconds: number } | null>(null);
const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);
useEffect(() => {
if (!socket) return;
socket.on('checkers:afk_warning', ({ playerId, secondsRemaining }) => {
setWarning({ isSelf: playerId === myPlayerId, seconds: secondsRemaining });
intervalRef.current = setInterval(() => {
setWarning(prev => {
if (!prev || prev.seconds <= 1) {
clearInterval(intervalRef.current!);
return null;
}
return { ...prev, seconds: prev.seconds - 1 };
});
}, 1000);
});
socket.on('checkers:afk_warning_cleared', () => {
clearInterval(intervalRef.current!);
setWarning(null);
});
return () => {
socket.off('checkers:afk_warning');
socket.off('checkers:afk_warning_cleared');
clearInterval(intervalRef.current!);
};
}, [socket, myPlayerId]);
if (!warning) return null;
return (
<div
role="alert"
className={`fixed top-4 left-1/2 -translate-x-1/2 z-50 px-6 py-3 rounded-xl font-semibold text-white shadow-lg ${
warning.isSelf ? 'bg-red-600' : 'bg-yellow-600'
}`}
>
{warning.isSelf
? `⚠️ Make a move in ${warning.seconds}s or you'll forfeit!`
: `⏳ Opponent has ${warning.seconds}s to move…`}
</div>
);
}Using the SDK? The
CheckersBoard component from @beta-gamer/react, @beta-gamer/react-native, and @beta-gamer/angular includes a built-in AFK banner by default. Pass showAfkWarning={false} to disable it and use your own implementation below.⚠️ Always show the AFK banner. Players should never be forfeited without a visible countdown.
Beta Gamer GaaS API — questions? support@beta-gamer.com