Hospedagem de Game Server
Última atualização: 15 de setembro de 2026
Um game server é um programa que você escreve e que mantém uma ou mais salas ativas — uma instância autoritativa do seu jogo onde os players realmente jogam. O SDK de servidor oferece a classe base Room para a sua lógica e um RoomHost que executa suas salas, registra-as no PlayServ, mantém-nas vivas com um heartbeat e as aposenta quando terminam. Levar um jogador até uma sala é papel do cliente (Matchmaking e Salas, Conectando-se a um Jogo); esta página é sobre o servidor que é dono da sala.
Este é o SDK do lado do servidor (PlayServ.Sdk.Rooms), usado por um programa que você implanta como game server — não pelo cliente do jogo. Ele se autentica como servidor, então não está sujeito às permissões de tabela voltadas ao cliente. Um game server pode ser uma instância gerenciada que a plataforma lança para você, ou um processo externo que você mesmo roda; ambos usam o mesmo SDK.
A forma de um game server
Dois tipos fazem o trabalho: uma subclasse de Room guarda o seu jogo, e um RoomHost executa salas desse tipo.
Uma sala mínima
Você cria uma subclasse de Room<TPlayer, TConfig> com seus próprios tipos de jogador e de configuração. A classe base gerencia o roster (AddPlayer, RemovePlayer, Players) e expõe hooks de ciclo de vida que você sobrescreve.
using PlayServ.Sdk.Rooms;
public sealed class MyPlayer : RoomPlayer { }
public sealed record MyConfig;
public sealed class MyRoom : Room<MyPlayer, MyConfig>
{
protected override void OnPlayerJoined(MyPlayer p) { /* dar um assento */ }
protected override void OnPlayerLeft(MyPlayer p) { /* liberar o assento */ }
protected override void OnTick(float dt) { /* avançar a sala */ }
}
Um RoomHost executa salas desse tipo a partir de uma fábrica:
var host = new RoomHost<MyRoom, MyPlayer, MyConfig>(name => new MyRoom());
var room = host.GetOrCreate("lobby-1");
Isso já é um servidor autoritativo funcional: o host conecta o heartbeat, registra a sala, aplica a configuração que puxa da plataforma e cuida do tempo de vida da sala.
Autorregistro e heartbeat
Você não informa suas salas à plataforma com uma chamada separada — o host registra cada sala automaticamente e a mantém atualizada com um heartbeat periódico que reporta ocupação e capacidade. Esse é exatamente o sinal que o navegador de salas do cliente lê, então uma sala fica descobrível assim que entra em execução e some da navegação pouco depois que o servidor para de enviar heartbeat por ela.
A configuração de sala é da plataforma
As configurações de sala — capacidade, tempo de vida da reserva, tempo de vida da sala, timeout de inatividade e a cota max_rooms por servidor — são de propriedade da plataforma e editadas no Backoffice, não embarcadas no seu código nem em um manifesto. O host puxa a configuração ao vivo e a aplica conforme muda, então um operador pode retunar um tipo de sala sem um redeploy.
// capacidade e limites vêm da plataforma, não do construtor —
// leia-os da sala em vez de assumir um valor definido no código
Como a config é puxada, mudar a capacidade ou um timeout no Backoffice passa a valer no servidor em execução dentro de um heartbeat. Não fixe esses valores no código; trate o que a plataforma entrega como a fonte da verdade.
Reportar onde a sala está
Um cliente precisa saber como alcançar a sala. Seu servidor declara seus dados de conexão — host, porta, transporte e, opcionalmente, um connect string e uma região — com DeclareConnect, e a plataforma os devolve ao cliente na sua reserva.
DeclareConnect(new RoomConnect { Host = publicHost, Port = port, Transport = "udp" }, region: "eu");
Quando a plataforma lançou o servidor para você (uma instância gerenciada), os dados de conexão podem ser preenchidos a partir do ambiente do orquestrador automaticamente; quando você roda o seu próprio processo, você os declara.
O ciclo de vida da sala
Uma sala passa por um ciclo de vida pequeno e bem definido. O host conduz a maior parte; você influencia pelos hooks e por algumas declarações.
| Estágio | O que acontece |
|---|---|
| Aberta | A sala aceita novos jogadores; o navegador pode exibi-la. |
| Ocupada | Jogadores entram e saem; OnPlayerJoined / OnPlayerLeft disparam; o heartbeat reporta a contagem viva. |
| Ociosa | Todos saíram. OnIdle dispara; você pode pausar a simulação ou deixar a limpeza aposentar a sala. |
| Drenando | Perto do fim da vida, a sala para de aceitar novos jogadores enquanto os atuais terminam. |
| Fechada | A sala é aposentada. Fechar marca a sala como fechada em vez de excluí-la, e invalida os tickets de reserva que apontam para ela. |
Duas limpezas rodam sem qualquer trabalho seu: a limpeza por ociosidade aposenta salas sem ninguém, e a limpeza por tempo de vida impõe a idade máxima da sala. Ambas respeitam a config de propriedade da plataforma acima.
Um jogador que cai mantém o assento por uma breve tolerância de reconex ão antes de a sala reportá-lo como ausente, para que uma oscilação de rede não custe o lugar dele. Declare-a com DeclareReconnect(...).
Aceitando jogadores
Um jogador chega ao seu servidor carregando uma reserva que obteve do SDK cliente. O host valida essa reserva antes de o jogador contar como presente: ela precisa ser válida, não gasta e emitida para esta sala. Só então OnPlayerJoined dispara.
- Uma reserva válida → o jogador é sentado;
OnPlayerJoined(player)roda. - Uma reserva ausente, expirada, de sala errada ou já gasta → a entrada é recusada.
É por isso que cliente e servidor são duas metades de um sistema: o cliente reserva e conecta, e o host que você escreve resgata a reserva. Você não valida tickets à mão — o host faz isso — mas você decide o que acontece em OnPlayerJoined / OnPlayerLeft: atribuir um spawn, adicioná-lo ao roster que você transmite, iniciar os timers dele.
Onde o servidor roda
Um game server pode rodar de algumas formas, e a plataforma mostra qual para cada sala:
- Gerenciado — a plataforma lança a instância do servidor para você por um orquestrador gerenciado (o PlayServ integra-se com o Edgegap). O token do orquestrador é do seu próprio estúdio, mantido por projeto e ambiente.
- Externo — você roda o servidor você mesmo (sua própria frota ou máquina). Você o declara ao PlayServ com
playserv functions declarecomo um game server, e ele registra suas salas como qualquer outro. Nunca precisa ser implantado como cloud function. - Pooled — uma sala servida a partir de um pool pré-provisionado.
De todo modo o modelo de sala é idêntico: registrar, heartbeat, aceitar reservas, reportar presença.
Capacidade e a cota de lançamentos
Dois limites diferentes se aplicam. Uma sala tem capacidade — os assentos dentro dela, vindos da config da plataforma. Um game server tem uma cota de salas (max_rooms) — quantas salas podem rodar ao mesmo tempo. Ao atingir a cota, a plataforma recusa lançar outra sala antes de qualquer chamada paga ao orquestrador, então um descontrole nunca vira uma conta alta.
Ambiente
Um servidor gerenciado recebe o que precisa por variáveis de ambiente PLAYSERV_* — a mais importante, PLAYSERV_DEPLOYMENT_TOKEN, que o SDK troca por uma sessão usada para falar com a plataforma. Você não define isso à mão em um lançamento gerenciado; para um servidor externo, você fornece os equivalentes para o SDK autenticar e registrar.
Próximos passos
- Simulação Autoritativa — o loop de tick, os sim systems e o streaming de estado para os clientes
- Matchmaking e Salas — o cliente que navega e reserva as salas que este servidor hospeda
- Conectando-se a um Jogo — como um cliente alcança e entra em uma sala hospedada