Fundamentals: your first resource in QBCore · Lesson 4/5 · 11 min
Your first script: a command that gives money (done right)
A server-authoritative /cobrar with QBCore, validation and cooldown, with no security holes.
Let's put it all together in a real script: a command that pays the player with QBCore, but done smartly — decided on the server and with a cooldown so it can't be abused.
config.lua (shared)
Config = {}
Config.Pago = 250 -- how much it pays
Config.CooldownSegundos = 60 -- how often it can be usedconfig.lua
server.lua (the authority)
local QBCore = exports['qb-core']:GetCoreObject()
local ultimoUso = {} -- [src] = timestamp
RegisterCommand('cobrar', function(source)
local src = source
if src == 0 then return end -- 0 = console, ignore
local ahora = os.time()
if ultimoUso[src] and (ahora - ultimoUso[src]) < Config.CooldownSegundos then
return QBCore.Functions.Notify(src, 'You can\'t collect yet.', '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, ('You collected $%s'):format(Config.Pago), 'success')
end, false)server.lua
Notice: the decision (how much, when, to whom) is 100% on the server. The client doesn't send amounts or anything tamperable. That's server-authoritative. The third argument of AddMoney ('comando-cobrar') is the reason, which QBCore records in the logs.
If you put the AddMoney on the client, anyone with a cheat menu would give themselves infinite money. That's why money is ALWAYS moved on the server.
Practice what you learned
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?
Challenge: code it yourself
Extend the command so it logs each payout to the console with the player's ID and the amount, and so the cooldown is configurable from Config.
Write it yourself in your editor (VS Code) and test it on your server. You learn here by doing it, not by copying.
See hint
A print(('Player %s collected %s'):format(src, Config.Pago)) right after validating the cooldown.
Escribe aquí tu solución:
