QBCore Structure and Core Object
Everything in QBCore hangs off one shared table exported by qb-core. Learn its
shape and most community scripts become readable.
Getting the core object
local QBCore = exports['qb-core']:GetCoreObject()Call this once at the top of a client or server script. The returned table
exposes QBCore.Functions, QBCore.Shared, QBCore.Commands and
QBCore.Player.
Player data
Each connected player has a PlayerData table. The columns that persist are
stored as JSON in the players table and decoded on login.
PlayerData = {
source = 1,
citizenid = 'ABC12345',
license = 'license:...',
name = 'John Doe',
money = { cash = 500, bank = 5000, crypto = 0 },
charinfo = {
firstname = 'John',
lastname = 'Doe',
birthdate = '1990-01-01',
gender = 0,
nationality = 'USA',
phone = '555-0123',
},
job = {
name = 'police',
label = 'Police',
onduty = true,
isboss = false,
type = 'leo',
grade = { name = 'Officer', level = 1, payment = 100, isboss = false },
},
gang = { name = 'none', label = 'No Gang', grade = { name = 'none', level = 0 } },
position = vector4(0.0, 0.0, 0.0, 0.0),
metadata = { hunger = 100, thirst = 100, stress = 0, isdead = false, armor = 0 },
}job.grade.level is a number on PlayerData, but grades are keyed by
string in qb-core/shared/jobs.lua. Mixing the two up is the most common
cause of “job not found” on a SetJob call.
metadata is a free-form table. Community scripts write into it liberally, which
is why it is the thing most likely to differ between two QBCore servers.
Player data reference → · Database schema →
Common server calls
local QBCore = exports['qb-core']:GetCoreObject()
-- Fetch a player
local Player = QBCore.Functions.GetPlayer(source)
local Player = QBCore.Functions.GetPlayerByCitizenId('ABC12345')
local players = QBCore.Functions.GetQBPlayers()
-- Money
Player.Functions.AddMoney('cash', 100, 'paycheck')
Player.Functions.RemoveMoney('bank', 50, 'atm-fee')
local cash = Player.Functions.GetMoney('cash')
-- Inventory
Player.Functions.AddItem('water_bottle', 1)
Player.Functions.RemoveItem('lockpick', 1)
local item = Player.Functions.GetItemByName('phone')
-- Job and metadata
Player.Functions.SetJob('police', 1)
Player.Functions.SetMetaData('stress', 0)
Player.Save()Always pass a reason string to AddMoney and RemoveMoney. It lands in the
money logs and is the difference between a five-minute and a five-hour
investigation when an economy exploit turns up.
Server functions → · Client functions →
Shared data
QBCore.Shared holds the server-wide definitions loaded from
qb-core/shared/:
| Table | File | Contents |
|---|---|---|
QBCore.Shared.Items | items.lua | Every item definition |
QBCore.Shared.Jobs | jobs.lua | Jobs and their grade tables |
QBCore.Shared.Gangs | gangs.lua | Gangs and their grade tables |
QBCore.Shared.Vehicles | vehicles.lua | Purchasable vehicles and prices |
QBCore.Shared.Weapons | weapons.lua | Weapon hashes and ammo types |
These are read at resource start. To change them at runtime, use the shared mutation exports rather than editing the tables directly.
Shared data → · Shared exports →
Key events
| Event | Side | Fires when |
|---|---|---|
QBCore:Server:PlayerLoaded | Server | A character finishes loading |
QBCore:Client:OnPlayerLoaded | Client | The client is ready to play |
QBCore:Server:OnPlayerUnload | Server | A character logs out |
QBCore:Server:PlayerDropped | Server | A player disconnects |
QBCore:Server:OnJobUpdate | Server | A player’s job changes |
QBCore:Server:OnGangUpdate | Server | A player’s gang changes |
QBCore:Server:OnPlayerUpdated | Server | Any PlayerData key changes |
QBCore:Client:OnPlayerUpdated | Client | PlayerData is pushed to the client |
Never trust a client-triggered event that carries money, items or a job name.
Fetch the player server-side with GetPlayer(source) and validate there. See
FiveM events for the general rule.
Server events → · Client events → · Commands →
Next steps
- QBCore resources — what ships with the framework
- Writing your first script
- Custom resource development →