Fundamentos: tu primer recurso en QBCore · Lección 4/5 · 11 min
Tu primer script: un comando que da dinero (bien hecho)
Un /cobrar server-authoritative con QBCore, validación y cooldown, sin agujeros de seguridad.
Vamos a juntar todo en un script real: un comando que paga al jugador con QBCore, pero hecho con cabeza — decidido en el servidor y con un cooldown para que no se abuse.
config.lua (compartido)
Config = {}
Config.Pago = 250 -- cuánto paga
Config.CooldownSegundos = 60 -- cada cuánto se puede usarconfig.lua
server.lua (la autoridad)
local QBCore = exports['qb-core']:GetCoreObject()
local ultimoUso = {} -- [src] = timestamp
RegisterCommand('cobrar', function(source)
local src = source
if src == 0 then return end -- 0 = consola, ignorar
local ahora = os.time()
if ultimoUso[src] and (ahora - ultimoUso[src]) < Config.CooldownSegundos then
return QBCore.Functions.Notify(src, 'Aún no puedes cobrar.', 'error')
end
ultimoUso[src] = ahora
local Player = QBCore.Functions.GetPlayer(src)
if not Player then return end
Player.Functions.AddMoney('cash', Config.Pago, 'comando-cobrar')
QBCore.Functions.Notify(src, ('Has cobrado $%s'):format(Config.Pago), 'success')
end, false)server.lua
Fíjate: la decisión (cuánto, cuándo, a quién) está 100% en el servidor. El cliente no envía cantidades ni nada manipulable. Eso es server-authoritative. El tercer argumento de AddMoney ('comando-cobrar') es el motivo, que QBCore registra en los logs.
Si pusieras el AddMoney en el cliente, cualquiera con un menú trampa se daría dinero infinito. Por eso el dinero SIEMPRE se mueve en el servidor.
Practica lo aprendido
0/3Completa para obtener el objeto del core y el jugador en el servidor a partir de su source.
local QBCore = exports['qb-core']:()local Player = QBCore.Functions.GetPlayer(source)Pista
El core de QBCore se importa por export, no por import en el manifest.
Falta comprobar que el jugador existe antes de darle dinero. Añade el guard justo después de obtenerlo.
Este código tiene un fallo:
local Player = QBCore.Functions.GetPlayer(source)Player.Functions.AddMoney('cash', 250)Reescríbelo corregido:
Pista
Si GetPlayer devuelve nil, Player.Functions peta. Añade 'if not Player then return end' antes de tocar al jugador.
¿Por qué el AddMoney del comando /cobrar va en el servidor y no en el cliente?
Reto: prográmalo tú
Amplía el comando para que registre por consola cada cobro con el ID del jugador y la cantidad, y para que el cooldown sea configurable desde Config.
Escríbelo tú en tu editor (VS Code) y pruébalo en tu servidor. Aquí se aprende haciéndolo, no copiando.
Ver pista
Un print(('Jugador %s cobró %s'):format(src, Config.Pago)) justo después de validar el cooldown.
Escribe aquí tu solución:
