Proyecto final: una tienda 24/7 con QBCore · Lección 3/4 · 11 min

El servidor: compra validada

El corazón de la tienda: un callback (o evento) que comprueba el precio desde Config, cobra y entrega.

Aquí está lo importante: el servidor recibe SOLO el nombre del item, busca su precio en Config, comprueba que el jugador tiene dinero, cobra y entrega. Con anti-spam para evitar abusos.

lua
-- server.lua
local QBCore = exports['qb-core']:GetCoreObject()
local ultimo = {}

local function precioDe(itemName)
  for _, p in ipairs(Config.Productos) do
    if p.item == itemName then return p.precio end
  end
  return nil
end

RegisterNetEvent('tienda:server:comprar', function(itemName)
  local src = source
  local Player = QBCore.Functions.GetPlayer(src)
  if not Player then return end

  -- anti-spam
  local ahora = GetGameTimer()
  if ultimo[src] and (ahora - ultimo[src]) < 500 then return end
  ultimo[src] = ahora

  -- precio desde el SERVIDOR
  local precio = precioDe(itemName)
  if not precio then return end -- item no está en el catálogo

  -- cobra (RemoveMoney valida saldo y devuelve true/false)
  if Player.Functions.RemoveMoney('cash', precio, 'tienda-247') then
    Player.Functions.AddItem(itemName, 1)
    TriggerClientEvent('inventory:client:ItemBox', src, QBCore.Shared.Items[itemName], 'add')
    QBCore.Functions.Notify(src, 'Comprado', 'success')
  else
    QBCore.Functions.Notify(src, 'No tienes suficiente efectivo', 'error')
  end
end)

server.lua

Cuenta los blindajes: jugador existe, anti-spam, el item está en Config (precio válido), y RemoveMoney comprueba el saldo antes de entregar. Sin uno de esos checks, un tramposo se lleva items gratis.

Practica lo aprendido

0/3
Ordena el código

Ordena el evento de compra del servidor: obtener jugador, anti-spam, precio desde Config, cobrar y entregar.

Coloca las líneas en el orden correcto con las flechas.

local Player = QBCore.Functions.GetPlayer(src)
local precio = precioDe(itemName)
Player.Functions.AddItem(itemName, 1)
end)
RegisterNetEvent('tienda:server:comprar', function(itemName)
if Player.Functions.RemoveMoney('cash', precio, 'tienda-247') then
if not Player then return end
end
local src = source
if not precio then return end
Pista

source primero, guard del jugador, precio de Config, y solo entregas si RemoveMoney devuelve true.

Rellena los huecos

Completa el guard que comprueba que el jugador existe antes de tocar su dinero.

1local Player = QBCore.Functions.GetPlayer(src)
2if not then return end
Pista

GetPlayer puede devolver nil si el jugador no está cargado; córtalo ahí.

Corrige el error

Este evento entrega el item sin comprobar que existe en QBCore.Shared.Items, así que un item mal escrito en Config rompe el inventario. Añade esa validación antes de cobrar.

Este código tiene un fallo:

1local precio = precioDe(itemName)
2if not precio then return end
3if Player.Functions.RemoveMoney('cash', precio, 'tienda-247') then
4 Player.Functions.AddItem(itemName, 1)
5end

Reescríbelo corregido:

Pista

Comprueba QBCore.Shared.Items[itemName] justo después de validar el precio y antes de RemoveMoney.

Reto: prográmalo tú

Añade un límite: que no se pueda comprar si el item no existe en QBCore.Shared.Items (item mal escrito en Config).

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

Ver pista

if not QBCore.Shared.Items[itemName] then return end antes de RemoveMoney.

Escribe aquí tu solución:

¿Qué tal esta lección?