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.

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. En QBCore esto es exactamente igual de peligroso que en ESX.

El error típico (vulnerable)

lua
-- ❌ MAL: confía en la cantidad y el precio que manda el cliente
RegisterNetEvent('tienda:server:vender', function(cantidad, precio)
  local Player = QBCore.Functions.GetPlayer(source)
  Player.Functions.AddMoney('cash', cantidad * 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', function(itemName, cantidad)
  local src = source
  local Player = QBCore.Functions.GetPlayer(src)
  if not Player 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 = Player.Functions.GetItemByName(itemName)
  if not item or item.amount < cantidad then return end

  Player.Functions.RemoveItem(itemName, cantidad)
  Player.Functions.AddMoney('cash', precio * cantidad, 'venta-' .. itemName)
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 (GetItemByName, dinero, trabajo, distancia).

Practica lo aprendido

0/3
Test

¿Por qué es peligroso un RegisterNetEvent que se fía de los datos del cliente?

Corrige el error

Este evento de venta confía en el precio que manda el cliente (dinero infinito). Arréglalo: el precio debe salir de Config en el servidor, no de los argumentos.

Este código tiene un fallo:

1RegisterNetEvent('tienda:server:vender', function(cantidad, precio)
2 local Player = QBCore.Functions.GetPlayer(source)
3 Player.Functions.AddMoney('cash', cantidad * precio)
4end)

Reescríbelo corregido:

Pista

Quita 'precio' de los argumentos, recibe itemName, y léelo con Config.Precios[itemName] dentro del servidor.

Rellena los huecos

Completa la primera línea del cuerpo del evento: guarda el source y obtén el Player, comprobando que existe.

1RegisterNetEvent('tienda:server:vender', function(itemName, cantidad)
2 local src = source
3 local Player = QBCore.Functions.GetPlayer(src)
4 if not then return end
5end)
Pista

El jugador puede no estar cargado; el guard corta la ejecución si GetPlayer devolvió nil.

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 esté 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 AddItem.

Escribe aquí tu solución:

¿Qué tal esta lección?