Cliente y servidor a fondo · Lección 1/4 · 10 min

Eventos seguros: no te fíes del cliente

Cualquier jugador puede disparar tus eventos de red con los datos que quiera. Aprende a validarlos para que no te roben el servidor.

Un RegisterNetEvent es una puerta abierta: cualquier jugador puede dispararlo desde su cliente con los argumentos que le dé la gana. Si no validas, le estás regalando trampas.

El error típico (vulnerable)

lua
-- ❌ MAL: confía en la cantidad que manda el cliente
RegisterNetEvent('tienda:server:vender')
AddEventHandler('tienda:server:vender', function(cantidad, precio)
  local xPlayer = ESX.GetPlayerFromId(source)
  xPlayer.addMoney(cantidad * precio) -- el cliente manda cantidad Y precio = dinero infinito
end)

Vulnerable

Aquí un tramposo manda cantidad=99999 y precio=99999 y se forra. El precio y la lógica NUNCA deben venir del cliente.

La versión segura

lua
RegisterNetEvent('tienda:server:vender')
AddEventHandler('tienda:server:vender', function(itemName, cantidad)
  local src = source
  local xPlayer = ESX.GetPlayerFromId(src)
  if not xPlayer then return end

  -- 1) valida tipos y rangos
  cantidad = tonumber(cantidad)
  if not cantidad or cantidad < 1 or cantidad > 100 then return end

  -- 2) el PRECIO lo decide el servidor, no el cliente
  local precio = Config.Precios[itemName]
  if not precio then return end

  -- 3) comprueba que el jugador TIENE lo que dice vender
  local item = xPlayer.getInventoryItem(itemName)
  if not item or item.count < cantidad then return end

  xPlayer.removeInventoryItem(itemName, cantidad)
  xPlayer.addMoney(precio * cantidad)
end)

Validación completa

  • Valida tipo y rango de cada argumento (tonumber, límites).
  • Precios, recompensas y lógica salen de Config o BD en el servidor, nunca del cliente.
  • Comprueba que el jugador tiene/puede hacer lo que pide (item, dinero, trabajo, distancia).

Practica lo aprendido

0/3
Test

Un evento de servidor hace: xPlayer.addMoney(cantidad * precio), donde cantidad y precio llegan como argumentos del cliente. ¿Por qué es un agujero?

Pista

¿Quién controla los valores que llegan en los argumentos?

Rellena los huecos

Completa la validación segura: convierte la cantidad a número, comprueba el rango y saca el precio del servidor.

1cantidad = (cantidad)
2if not cantidad or cantidad < 1 or cantidad > 100 then return end
3local precio = [itemName]
4if not precio then return end
Pista

Primero valida el tipo numérico; el precio sale de tu tabla de Config.

Corrige el error

Blinda este evento vulnerable: el precio NO puede venir del cliente, debe salir de Config, y valida la cantidad con tonumber.

Este código tiene un fallo:

1RegisterNetEvent('tienda:server:vender')
2AddEventHandler('tienda:server:vender', function(cantidad, precio)
3 local xPlayer = ESX.GetPlayerFromId(source)
4 xPlayer.addMoney(cantidad * precio)
5end)

Reescríbelo corregido:

Pista

Quita 'precio' de los argumentos y léelo de Config.Precios[itemName].

Reto: prográmalo tú

Coge un evento que dé un item al jugador y blíndalo: que valide la cantidad (1-10) y que el item exista en una lista de Config permitidos.

Escríbelo tú en tu editor (VS Code) y pruébalo en tu servidor. Aquí se aprende haciéndolo, no copiando.

Ver pista

tonumber + comprobar rango + Config.ItemsPermitidos[item] antes de addInventoryItem.

Escribe aquí tu solución:

¿Qué tal esta lección?