qbx_core
if GetResourceState('qbx_core') ~= 'started' then return end
Framework = {
tables = {
players = 'players'
},
columns = {
players = {
identifier = 'citizenid',
fullname = "CONCAT(JSON_UNQUOTE(JSON_EXTRACT(p.`charinfo`, '$.firstname')), ' ', JSON_UNQUOTE(JSON_EXTRACT(p.`charinfo`, '$.lastname')))",
job = "JSON_ARRAY(CONCAT(JSON_VALUE(p.`job`, '$.label'),' (',JSON_VALUE(p.`job`, '$.name'),')'))"
}
},
--[[
IdentityStats Configuration:
`IdentityStats` is an array that defines how certain identity information is retrieved from the database.
Each entry in the array represents a different identity category and contains:
- `table`: The database table where the identity data is found.
- `column`: Specifies which column to fetch. Use '*' for all columns.
- `identifier`: The column used to match a specific row (e.g., fetching data for a particular user).
- `value`: Specifies the keys or columns you want to retrieve. This is especially useful when fetching from JSON columns.
- `label`: Defines how the data is presented. Placeholders (like {nationality}) get replaced by the corresponding values from the database.
- `enabled`: Determines if this category is active or not.
Example:
For the configuration:
table = "players",
column = "charinfo",
identifier = "citizenid",
value = { "nationality", "birthdate" },
label = { "Nationality: {nationality}", "Birthdate: {birthdate}" },
This would fetch the `nationality` and `birthdate` from the `charinfo` column in the `players` table where `citizenid` matches the given identifier.
It then labels them as "Nationality: <value>" and "Birthdate: <value>".
]]
IdentityStats = {
{
table = "players",
column = "charinfo",
identifier = "citizenid",
value = { "nationality", "birthdate", "phone", "gender" },
label = { "Nationality: {nationality}", "Birthdate: {birthdate}", "Phone: {phone}", "Gender: {gender}" },
enabled = true
},
-- {
-- table = "players",
-- column = "metadata",
-- identifier = "citizenid",
-- value = { "fingerprint", "walletid", "bloodtype" },
-- label = { "Fingerprint: {fingerprint}", "Wallet ID: {walletid}", "Bloodtype: {bloodtype}" },
-- enabled = true
-- },
{
table = "drx_mdt_player_link",
column = "points",
identifier = "identifier",
value = nil,
label = "Points",
enabled = true
}
-- Example of pulling all columns from a table
-- {
-- table = "player_vehicles",
-- column = "*",
-- identifier="citizenid",
-- value={"vehicle", "hash", "plate"},
-- label = {"Vehicle: {vehicle}", "Hash: {hash}", "Plate: {plate}"},
-- enabled = true
-- }
},
VehicleStats = {
{
table = "player_vehicles",
column = "*",
identifier = "plate",
value = {"fakeplate", "depotprice"},
label = {"Known plate: {fakeplate}", "Depot price: {depotprice}"},
enabled = true
},
{
table = "player_vehicles",
column = "mods",
identifier = "plate",
value = {"modTurbo", "modXenon", "modExhaust"},
label = {"Turbo: {modTurbo}", "Xenon: {modXenon}", "Aftermarket exhaust: {modExhaust}"},
enabled = true
}
},
---@param src number The player server id
getPlayerBySource = function(src)
local player = {}
local qb = exports.qbx_core:GetPlayer(src)
if not qb then
return nil
end
player.source = qb.PlayerData.source
player.identifier = qb.PlayerData.citizenid
player.fullname = qb.PlayerData.charinfo.firstname .. ' ' .. qb.PlayerData.charinfo.lastname
return player
end,
---@param identifier string The player framework identifier
getPlayerByIdentifier = function(identifier)
local player = {}
local qb = exports.qbx_core:GetPlayerByCitizenId(identifier)
if not qb then
return nil
end
player.PlayerData = qb.PlayerData
player.Functions = qb.Functions
player.source = qb.PlayerData.source
player.identifier = qb.PlayerData.citizenid
player.fullname = qb.PlayerData.charinfo.firstname .. ' ' .. qb.PlayerData.charinfo.lastname
return player
end,
---@param src number The player server id
getPlayerIdentifier = function(src)
local qb = exports.qbx_core:GetPlayer(src)
if not qb then return nil end
return qb.PlayerData.citizenid
end,
---@param src number The player server id (officer)
---@param identifier string The player framework identifier (criminal)
---@param fine number The fine amount
finePlayer = function(source, identifier, fine)
local xTarget = Framework.getPlayerByIdentifier(identifier)
if xTarget then
xTarget.Functions.RemoveMoney('bank', fine)
return
end
MySQL.update.await(
("UPDATE %s SET money = JSON_SET(`money`, '$.bank', JSON_UNQUOTE(JSON_EXTRACT(`money`, '$.bank')) - ?) WHERE %s = ?"):format(Framework.tables.players,
fine, Framework.columns.players.identifier), { fine, identifier })
-- If you want to add the fine to the police department, then uncomment the line below
-- exports['qb-management']:AddMoney("police", fine)
end,
---@param src number The player server id (officer)
---@param identifier string The player framework identifier (criminal)
---@param jailtime number The jailtime in minutes
jailPlayer = function(source, identifier, jailtime)
local xTarget = Framework.getPlayerByIdentifier(identifier)
if xTarget then
xTarget.Functions.SetMetaData("injail", jailtime)
TriggerClientEvent("police:client:SendToJail", xTarget.PlayerData.source, jailtime)
return
end
-- If you want to add the jailtime to an offline player, then uncomment the line below
-- MySQL.update.await(("UPDATE %s SET metadata = JSON_SET(metadata, '$.injail', ?) WHERE %s = ?"):format(Framework.tables.players,
-- Framework.columns.players.identifier), { jailtime, identifier })
end,
---@param identifier string The player framework identifier
---@param job string The job name
---@param grade number The job grade level
setJob = function(identifier, job, grade)
local Player = exports.qbx_core:GetPlayerByCitizenId(identifier)
if not Player then
local shared = exports.qbx_core:GetJobs()
if not shared[job] then return 0 end
local j = {
name = job,
label = shared[job].label,
type = shared[job].type,
onduty = false,
grade = {
name = shared[job].grades[grade].name,
level = grade
},
}
return MySQL.update.await(('UPDATE %s p SET p.`job` = ? WHERE %s = ?'):format(Framework.tables.players, Framework.columns.players.identifier), {
json.encode(j), identifier
})
end
Player.Functions.SetJob(job, tostring(grade))
return 1
end,
---Returns a list of all job names
---@return table<number, string>
getJobs = function()
local jobs = exports.qbx_core:GetJobs()
local jobNames = {}
for job, _ in pairs(jobs) do
jobNames[job] = true
end
Logger.debug('Jobs: %s', json.encode(jobNames))
return jobNames
end,
---@param stateid string The players state identifier
getCitizen = function(stateid)
local query = [[
SELECT
link.`stateid` as identifier,
link.`image`,
link.`gallery`,
link.`tags`,
link.`points`,
link.`wanted`,
link.`notes`,
p.%s as framework_identifier,
%s as fullname,
%s as job
FROM
`drx_mdt_player_link` link
INNER JOIN
%s p ON p.%s = link.`identifier`
WHERE
link.`stateid` = ?
GROUP BY link.`stateid`
]]
query = query:format(Framework.columns.players.identifier, Framework.columns.players.fullname, Framework.columns.players.job,
Framework.tables.players,
Framework.columns.players.identifier)
local result = MySQL.single.await(query, { stateid })
return result
end,
---@param term string The search term
---@param excludeStaff boolean Whether to exclude staff or not
searchPlayers = function(term, excludeStaff)
local query = [[
SELECT
link.`stateid` as identifier,
p.%s as framework_identifier,
link.`image`,
link.`tags`,
%s as fullname
FROM
`drx_mdt_player_link` link
JOIN
%s p ON p.%s = link.`identifier`
WHERE
(%s LIKE ?
OR link.`stateid` = ?)
%s
LIMIT 20
]]
local excludedWhere = excludeStaff and "AND NOT EXISTS (SELECT 1 FROM `drx_mdt_officers` o WHERE o.identifier = link.`stateid`)" or ""
query = query:format(Framework.columns.players.identifier, Framework.columns.players.fullname, Framework.tables.players, Framework.columns.players.identifier,
Framework.columns.players.fullname, excludedWhere)
return MySQL.query.await(query, { '%' .. term .. '%', term })
end,
}
RegisterNetEvent('QBCore:Server:OnPlayerLoaded', function()
local src = source
local identifier = Framework.getPlayerIdentifier(src)
if not identifier then return Logger.error('Failed to get player identifier for ', src) end
LoadOfficer(src, identifier)
end)
AddEventHandler('QBCore:Server:OnPlayerUnload', function()
local src = source
UnloadOfficer(src)
local clockStatus = exports.drx_mdt:GetOfficerClockedIn(src)
if clockStatus then
exports.drx_mdt:ToggleClock(src)
end
end)
AddEventHandler('onResourceStart', function(resource)
if resource ~= GetCurrentResourceName() then return end
local Players = exports.qbx_core:GetQBPlayers()
for key, value in pairs(Players) do
LoadOfficer(value.PlayerData.source, value.PlayerData.citizenid)
end
end)
Last updated