Skip to content

feat: multiplayer online com servidor autoritativo, sala por endereço e voz por proximidade - #33

Merged
thnbi merged 137 commits into
devfrom
feat/multiplayer
Oct 15, 2026
Merged

thnbi merged 137 commits into
devfrom
feat/multiplayer

Conversation

@thnbi

@thnbi thnbi commented Oct 14, 2026

Copy link
Copy Markdown
Contributor

Leva o multiplayer online para a dev: servidor de jogo autoritativo no Colyseus 0.18, sala de quatro por endereço na URL, bots do núcleo no servidor e voz por proximidade. A arquitetura, os números e as medições estão em docs/rede/arquitetura-de-rede.md; as decisões, nas ADRs 0002, 0006 e 0025 a 0028.

Sala e entrada

  • Matchmaking pela URL (POST /rooms/enter): /203.0.113.7 entra na sala desse endereço; cheia, o jogador espera numa sala provisória e é chamado quando a vaga abre. Só entra quem recebeu assento do matchmaking (onAuth), e a fila é conferida de novo quando uma reserva vence.
  • Mapa por sala: a sala nasce no mapa de quem a cria (um tipo de sala por mapa do catálogo); quem entra depois recebe o mapa dela e recarrega nele.
  • Bots do núcleo no servidor: completam as vagas que os humanos não ocupam, com as mesmas regras do jogador. Para o cliente, um bot é mais um jogador da sala.
  • Nomes: o nome de perfil vai na mensagem profile.callsign, o servidor o limpa com a regra do menu (agora no núcleo) e o põe no estado da sala.
  • O servidor serve o build do cliente e fala HTTPS/WSS com SHOBU_TLS_CERT e SHOBU_TLS_KEY.

Rede

  • Tick, input e patch a 60 Hz. O patch sai no fim de cada tick, e não num timer próprio: todo patch traz tick novo, e o buffer de interpolação caiu de 50 para 33,3 ms.
  • Predição e reconciliação do jogador local, com input quantizado (posição em 2 mm no int16, mira em 1/32767, direção em 1/127) e balde de crédito de 8 inputs no servidor. Medido contra o servidor real, 0 correções em 15 s andando, correndo, pulando e morrendo fora da área.
  • Rewind do tiro com lastSeenBy e janela de 150 ms; o golpe de lâmina ainda é contra as posições de agora (marcado como simplificação).
  • Mensagens: match.kill (o KillEvent do núcleo, cada cliente pontua a mesma lista), match.boundary-death, match.shot (rastro, clarão e som dos tiros dos outros), loadout.melee, profile.callsign.
  • Hitmarker previsto no quadro do disparo; placar, medalhas e killfeed seguem o servidor.
  • Instrumentação: ping da sala no HUD e, com ?perf=1, um resumo net.stats no console a cada 2 s.

Voz

LiveKit (WebRTC, Opus 24 kbps com RED e DTX), push-to-talk no T, e cada voz posta no corpo de quem fala (PannerNode com HRTF: volume cheio até 10 m, silêncio a partir de 45 m). A sinalização passa por um relay TLS dentro do servidor de jogo, na porta 7880. Sem servidor de mídia, o jogo roda sem voz.

Correções que vieram junto

  • Online, as kills da sala não chegavam ao killfeed nem às medalhas: o registro do quadro era zerado depois de a sala o preencher.
  • O respawn fora da área custava de 4 a 6 correções: a predição guardava o tick antes do limite da área.
  • O cliente subia o mapa salvo no menu enquanto o servidor simulava outro: spawn fora do mapa e rollback.
  • Posições a 1 mm estouravam o int16 nos mapas de 70 m.

Desenvolvimento

npm run dev --workspace @shobu/server sobe o servidor em :2567 com node --watch: ele reinicia a cada edição, núcleo incluso. Servidor velho rodando contra cliente novo foi a causa do lag mais grave desta branch.

Fica para depois

  • Fim de partida, MVP e voto de mapa no servidor (ADR 0022): online, a sala ainda não termina.
  • Rewind do golpe de lâmina.
  • Teste de aceitação com netem (ADR 0006), refeito a 60 Hz.
  • Domínio e certificado Let's Encrypt.

Verificação

npm run verify passa: lint, tipos e os testes de 272 arquivos com 100% de cobertura. Testado no Chrome contra o servidor local, com bots e voz.

thnbi added 28 commits October 14, 2026 19:17
@thnbi
thnbi merged commit ca9f3b1 into dev Oct 15, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant