Matches
How a match flows, and how to start, pause, limit and follow it.
Phases
A room moves through four phases, reported by getState().phase:
| Phase | What happens | Ends |
|---|---|---|
lobby | Players choose teams; there are no discs. | startGame() |
playing | The match runs at 60 ticks per second. | A goal, a win or stopGame() |
goal | The ball is dead for 5.5 seconds after a goal. | Kickoff positions reset |
finished | A team has won; the result shows for 5 seconds. | Returns to lobby |
A match is won when a team reaches the score limit, or when time runs out with one team ahead. If the score is level at the time limit, play continues until the next goal.
Control a match
await room.setScoreLimit(3); // 0 = no limit
await room.setTimeLimit(5); // minutes, 0 = no limit
await room.startGame();Score and time limits, like stadiums, change only between matches: during a match these calls do nothing. Set them before startGame().
pauseGame(true) freezes play; pauseGame(false) resumes after a two-second countdown. stopGame() ends the match without a winner.
Follow the match
Events tell you what happened; reads tell you where things stand.
room.onTeamGoal = (team) => {
const { red, blue, time } = room.getScores();
console.log(
`${Math.floor(time / 60)}' ` +
`${team === 1 ? 'Red' : 'Blue'} scores: ${red}–${blue}`,
);
};
room.onTeamVictory = ({ red, blue }) => {
void room.sendAnnouncement(
`Full time: Red ${red} – ${blue} Blue`,
null,
null,
'bold',
);
};onGameTick runs 60 times a second during play, before each simulation step. Use it for things that must track every moment, such as possession or heatmaps, and keep it fast: a slow handler slows the whole room. If your process stalls for more than half a second, the room pauses the match and reports Host scheduler stalled; match paused.
Keep matches going
A common pattern starts the next match automatically when one ends:
room.onGameStop = async () => {
const fielded = room
.getPlayerList()
.filter((p) => p.team !== 0);
if (fielded.length >= 2) {
await new Promise((resolve) => setTimeout(resolve, 3000));
await room.startGame();
}
};onGameStop fires both when a match is stopped and when a finished match returns to the lobby.
Kick spam
setKickRateLimit(min, rate, burst) limits how fast players can kick. It applies immediately, even mid-match.