Skip to Content

Qbox Structure and Core Exports

Qbox keeps QBCore’s data vocabulary but drops the shared core object. Everything goes through exports on qbx_core.

No core object

-- QBCore local QBCore = exports['qb-core']:GetCoreObject() local Player = QBCore.Functions.GetPlayer(source) -- Qbox local player = exports.qbx_core:GetPlayer(source)
ℹ️

There is no GetCoreObject() in Qbox. Calling exports directly means no startup ordering problem and no stale shared table, which is the main reason the fork made this change.

Qbox also exposes an ox_lib-style require for its shared modules:

local config = require '@qbx_core.config.shared'

Player data

PlayerData extends a PlayerEntity persisted to the database:

local player = exports.qbx_core:GetPlayer(source) player.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', account = 'US00QBX...', cid = 1, }, job = { name = 'police', label = 'Police', type = 'leo', onduty = true, isboss = false, grade = { name = 'Officer', level = 1, payment = 100 } }, jobs = { police = 1 }, gang = { name = 'none', label = 'No Gang', grade = { name = 'none', level = 0 } }, gangs = {}, position = vec4(0.0, 0.0, 0.0, 0.0), metadata = { health = 200, armor = 0, hunger = 100, thirst = 100, stress = 0, isdead = false, licences = {}, phone = {} }, }

The jobs and gangs tables are the multi-job feature: they map a job name to the grade level the player holds. Unemployed and gangless are not listed.

⚠️

PlayerData.items and player.Functions exist but are deprecated. Items live in ox_inventory; use its exports, not the player object.

Player type reference → 

Jobs and groups

Job and gang grades are numbers in Qbox, where QBCore used strings. This is the conversion bug that bites everyone.

-- qbx_core/shared/jobs.lua police = { label = 'Police', type = 'leo', defaultDuty = true, grades = { [0] = { name = 'Recruit', payment = 50 }, [1] = { name = 'Officer', payment = 75 }, }, },

Runtime management goes through exports, and does not persist across a restart:

exports.qbx_core:CreateJob('mechanic', jobTable) exports.qbx_core:AddPlayerToJob(citizenid, 'mechanic', 1) exports.qbx_core:RemoveJob('mechanic') local hasGroup = exports.qbx_core:HasGroup(source, 'police') local isBoss = exports.qbx_core:IsGradeBoss('police', 4)

Multi-job and multi-gang membership is stored in the player_groups table. Do not install external multijob resources — they write to the same tables and will corrupt data.

Common server calls

-- Players local player = exports.qbx_core:GetPlayer(source) local player = exports.qbx_core:GetPlayerByCitizenId('ABC12345') local players = exports.qbx_core:GetQBPlayers() -- Money exports.qbx_core:AddMoney(source, 'cash', 100, 'paycheck') local cash = exports.qbx_core:GetMoney(source, 'cash') -- Metadata and permissions local meta = exports.qbx_core:GetMetadata(source, 'stress') local ok = exports.qbx_core:HasPermission(source, 'admin') -- Items exports.qbx_core:CreateUseableItem('lockpick', function(source, item) end)

Server exports →  · Client exports → 

Events

Qbox deliberately keeps QBCore’s event names so that ported scripts keep working:

EventFires when
QBCore:Server:OnPlayerLoadedA character finishes loading
QBCore:Server:OnPlayerUnloadA character logs out
QBCore:Server:OnJobUpdateA player’s job changes
QBCore:Server:OnGangUpdateA player’s gang changes
QBCore:Server:OnMoneyChangeA money account changes
QBCore:Server:OnPermissionUpdateA player’s permissions change
qbx_core:server:onGroupUpdateMulti-job or multi-gang membership changes
qbx_core:server:onSetMetaDataA metadata key is written

The two qbx_core:-prefixed events are Qbox-only. Anything reading them will not run on QBCore.

Server events →  · Hooks → 

Next steps