Skip to content

Host rooms

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:

PhaseWhat happensEnds
lobbyPlayers choose teams; there are no discs.startGame()
playingThe match runs at 60 ticks per second.A goal, a win or stopGame()
goalThe ball is dead for 5.5 seconds after a goal.Kickoff positions reset
finishedA 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

JavaScript
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.

JavaScript
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:

JavaScript
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.