Andrade Systems
EntregueFiveMCliente: SIDE RP

side_amongus

Modo de jogo · Lua e React

O cliente nunca decide quem morreu, quem tem qual papel, quantos votos alguém recebeu ou quem venceu.

Lua
8.476 linhas
TypeScript e React
3.849 linhas
Minigames de tarefa
10
Partidas simultâneas
isoladas entre si

Fonte verificada no repositório interno em 08/09/2026

O que faz

Em uso

Um modo de dedução social completo rodando dentro de um servidor de roleplay: papéis ocultos, dez minigames de tarefa, sabotagens, reunião com votação, modo espectador, câmeras, dutos e recuperação de estado depois de queda de conexão.

A dificuldade não está nas mecânicas — está em rodar isso num ambiente onde o jogador controla o próprio cliente e várias partidas acontecem ao mesmo tempo, no mesmo servidor, sem que uma enxergue a outra.

Evidência

Como o sistema aparece

Capturas da interface real, renderizada com payload de demonstração derivado dos contratos do resource — organizações, cargos, pessoas e identificadores são sintéticos. Onde não existe interface, entra visualização técnica, rotulada como tal.

  • Interface do sistema

    Lobby: salas abertas, mapa, lotação e configuração da partida.

  • Interface do sistema

    Reunião na fase de votação. Quem morreu aparece riscado — mas quem conta o voto é o servidor.

  • Interface do sistema

    Fase de discussão, antes de a votação abrir.

  • Interface do sistema

    Escolha de personagem: cor já tomada aparece bloqueada antes do clique — o servidor recusaria de qualquer forma.

Por dentro da engenharia

Decisões de implementação

Um bloco por decisão de implementação. Abra o que interessa.

Servidor autoritativo para o estado da partida

Problema

Num servidor de FiveM, todo evento vindo do cliente está sob controle de quem quer trapacear. Um modo de dedução social é o pior caso possível: quem consegue afirmar "terminei a tarefa" ou "aquele ali morreu" ganha o jogo sem jogar.

Solução

Tudo o que chega do cliente atravessa uma camada única de validação antes de virar estado. Quem morreu, quem tem qual papel, se uma tarefa terminou, quantos votos alguém recebeu e quem venceu são decididos apenas no servidor. O evento do cliente é tratado como pedido, nunca como fato.

Por que foi feito assim

É a regra da própria documentação da plataforma, e é a única premissa que sobrevive a um jogador adversarial. Toda alternativa depende de o jogador escolher não mentir.

Isolamento entre partidas

Problema

Duas partidas rodando ao mesmo tempo no mesmo servidor veriam os jogadores uma da outra — e o restante da cidade veria as duas. Filtrar visibilidade à mão, evento por evento, é a solução que parece funcionar até a primeira que alguém esquece.

Solução

Cada partida recebe um contexto de roteamento próprio, alocado quando ela começa e devolvido quando termina, com a população do mundo desligada lá dentro.

Por que foi feito assim

Isolamento como primitiva do motor vale mais do que isolamento como disciplina do programador: não existe evento novo que esqueça de aplicá-lo.

Limite de frequência por jogador e por ação

Problema

Um limite único por jogador recusa o voto de alguém porque a pessoa acabou de abrir o tablet. O sintoma que chega ao suporte é "o servidor engoliu meu clique" — e a causa é praticamente impossível de rastrear a partir disso.

Solução

A chave do limite é o par jogador e ação. Abrir um painel não consome o orçamento de votar; votar não consome o de interagir.

Por que foi feito assim

O limite existe para impedir inundação de uma ação específica, não para impedir a pessoa de jogar. Quando ele erra o alvo, o custo aparece como bug de jogo e não como defesa funcionando.

Stack

O que foi usado

  • Servidor

    • Lua
    • FiveM
    • vRP
  • Interface

    • React
    • TypeScript
    • Vite
  • Estado

    • Contextos de roteamento por partida
    • Máquina de estados no servidor
    • Recuperação após queda de conexão