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)

lua
Config = {}
Config.Pago = 250            -- how much it pays
Config.CooldownSegundos = 60 -- how often it can be used

config.lua

server.lua (the authority)

lua
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/3
Rellena los huecos

Completa para obtener el objeto del core y el jugador en el servidor a partir de su source.

1local QBCore = exports['qb-core']:()
2local Player = QBCore.Functions.GetPlayer(source)
Pista

El core de QBCore se importa por export, no por import en el manifest.

Corrige el error

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:

1local Player = QBCore.Functions.GetPlayer(source)
2Player.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.

Test

¿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:

How was this lesson?