Comunicação cliente-servidor segura
No MTA:SA, cliente e servidor conversam o tempo todo: o jogador clica em "comprar", o servidor responde com o novo saldo, a interface se atualiza. Fazer isso direito evita exploits e lag.
O modelo certo
- Cliente pede (
triggerServerEvent); - Servidor valida tudo;
- Servidor executa e salva;
- Servidor responde só a quem precisa (
triggerClientEvent).
O cliente nunca decide preço, quantidade de dinheiro, dano, recompensa ou permissão.
Validação no servidor
addEvent("rp:comprarItem", true)
addEventHandler("rp:comprarItem", resourceRoot, function(idItem)
local jogador = client
if not jogador then return end
-- tipo do argumento
if type(idItem) ~= "string" then return end
-- item existe?
local item = ITENS[idItem]
if not item then return end
-- jogador está perto da loja?
if not estaPertoDaLoja(jogador) then return end
-- tem dinheiro?
if getPlayerMoney(jogador) < item.preco then
return triggerClientEvent(jogador, "rp:aviso", resourceRoot, "Dinheiro insuficiente")
end
takePlayerMoney(jogador, item.preco)
darItem(jogador, idItem)
triggerClientEvent(jogador, "rp:aviso", resourceRoot, "Compra realizada!")
end)
Pontos importantes:
- Use
client, nãosource, para saber quem enviou; - Verifique tipos e faixas dos argumentos;
- Confira contexto (posição, estado, cargo);
- O preço vem do servidor.
Limite de frequência
Clientes modificados podem disparar eventos milhares de vezes por segundo. Limite:
local ultimo = {}
local function podeUsar(jogador, intervaloMs)
local agora = getTickCount()
if ultimo[jogador] and agora - ultimo[jogador] < intervaloMs then return false end
ultimo[jogador] = agora
return true
end
addEventHandler("onPlayerQuit", root, function() ultimo[source] = nil end)
O MTA também oferece recursos nativos para detectar e limitar spam de eventos em versões recentes — consulte a wiki.
Envie só o necessário
- Em vez de enviar o inventário inteiro a cada mudança, envie apenas o item alterado;
- Evite
triggerClientEvent(root, ...)quando só um jogador precisa da informação; - Agrupe atualizações frequentes (ex.: a cada 1 segundo, não a cada mudança).
Dados grandes
Para enviar muitos dados de uma vez (ex.: lista de casas à venda), considere triggerLatentClientEvent, que envia em segundo plano com limite de banda, sem travar a conexão.
Registre tentativas suspeitas
Quando uma validação falhar de forma que só um cliente modificado causaria, registre em log (jogador, serial, evento, argumentos). Isso ajuda a identificar e banir trapaceiros.
Hospede seu servidor com a VittHost
No MTASA-BR da VittHost, seus sistemas rodam em servidores no Brasil com proteção DDoS, painel Pterodactyl, MySQL incluso, downloads acelerados por nginx dedicado e teste grátis de 3 dias.