721 lines
		
	
	
	
		
			26 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			721 lines
		
	
	
	
		
			26 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
QBCore.Functions = {}
 | 
						|
QBCore.Player_Buckets = {}
 | 
						|
QBCore.Entity_Buckets = {}
 | 
						|
QBCore.UsableItems = {}
 | 
						|
 | 
						|
-- Getters
 | 
						|
-- Get your player first and then trigger a function on them
 | 
						|
-- ex: local player = QBCore.Functions.GetPlayer(source)
 | 
						|
-- ex: local example = player.Functions.functionname(parameter)
 | 
						|
 | 
						|
---Gets the coordinates of an entity
 | 
						|
---@param entity number
 | 
						|
---@return vector4
 | 
						|
function QBCore.Functions.GetCoords(entity)
 | 
						|
    local coords = GetEntityCoords(entity, false)
 | 
						|
    local heading = GetEntityHeading(entity)
 | 
						|
    return vector4(coords.x, coords.y, coords.z, heading)
 | 
						|
end
 | 
						|
 | 
						|
---Gets player identifier of the given type
 | 
						|
---@param source any
 | 
						|
---@param idtype string
 | 
						|
---@return string?
 | 
						|
function QBCore.Functions.GetIdentifier(source, idtype)
 | 
						|
    if GetConvarInt('sv_fxdkMode', 0) == 1 then return 'license:fxdk' end
 | 
						|
    return GetPlayerIdentifierByType(source, idtype or 'license')
 | 
						|
end
 | 
						|
 | 
						|
---Gets a players server id (source). Returns 0 if no player is found.
 | 
						|
---@param identifier string
 | 
						|
---@return number
 | 
						|
function QBCore.Functions.GetSource(identifier)
 | 
						|
    for src, _ in pairs(QBCore.Players) do
 | 
						|
        local idens = GetPlayerIdentifiers(src)
 | 
						|
        for _, id in pairs(idens) do
 | 
						|
            if identifier == id then
 | 
						|
                return src
 | 
						|
            end
 | 
						|
        end
 | 
						|
    end
 | 
						|
    return 0
 | 
						|
end
 | 
						|
 | 
						|
---Get player with given server id (source)
 | 
						|
---@param source any
 | 
						|
---@return table
 | 
						|
function QBCore.Functions.GetPlayer(source)
 | 
						|
    if tonumber(source) ~= nil then -- If a number is a string ("1"), this will still correctly identify the index to use.
 | 
						|
        return QBCore.Players[tonumber(source)]
 | 
						|
    else
 | 
						|
        return QBCore.Players[QBCore.Functions.GetSource(source)]
 | 
						|
    end
 | 
						|
end
 | 
						|
 | 
						|
---Get player by citizen id
 | 
						|
---@param citizenid string
 | 
						|
---@return table?
 | 
						|
function QBCore.Functions.GetPlayerByCitizenId(citizenid)
 | 
						|
    for src in pairs(QBCore.Players) do
 | 
						|
        if QBCore.Players[src].PlayerData.citizenid == citizenid then
 | 
						|
            return QBCore.Players[src]
 | 
						|
        end
 | 
						|
    end
 | 
						|
    return nil
 | 
						|
end
 | 
						|
 | 
						|
---Get offline player by citizen id
 | 
						|
---@param citizenid string
 | 
						|
---@return table?
 | 
						|
function QBCore.Functions.GetOfflinePlayerByCitizenId(citizenid)
 | 
						|
    return QBCore.Player.GetOfflinePlayer(citizenid)
 | 
						|
end
 | 
						|
 | 
						|
---Get player by license
 | 
						|
---@param license string
 | 
						|
---@return table?
 | 
						|
function QBCore.Functions.GetPlayerByLicense(license)
 | 
						|
    return QBCore.Player.GetPlayerByLicense(license)
 | 
						|
end
 | 
						|
 | 
						|
---Get player by phone number
 | 
						|
---@param number number
 | 
						|
---@return table?
 | 
						|
function QBCore.Functions.GetPlayerByPhone(number)
 | 
						|
    for src in pairs(QBCore.Players) do
 | 
						|
        if QBCore.Players[src].PlayerData.charinfo.phone == number then
 | 
						|
            return QBCore.Players[src]
 | 
						|
        end
 | 
						|
    end
 | 
						|
    return nil
 | 
						|
end
 | 
						|
 | 
						|
---Get player by account id
 | 
						|
---@param account string
 | 
						|
---@return table?
 | 
						|
function QBCore.Functions.GetPlayerByAccount(account)
 | 
						|
    for src in pairs(QBCore.Players) do
 | 
						|
        if QBCore.Players[src].PlayerData.charinfo.account == account then
 | 
						|
            return QBCore.Players[src]
 | 
						|
        end
 | 
						|
    end
 | 
						|
    return nil
 | 
						|
end
 | 
						|
 | 
						|
---Get player passing property and value to check exists
 | 
						|
---@param property string
 | 
						|
---@param value string
 | 
						|
---@return table?
 | 
						|
function QBCore.Functions.GetPlayerByCharInfo(property, value)
 | 
						|
    for src in pairs(QBCore.Players) do
 | 
						|
        local charinfo = QBCore.Players[src].PlayerData.charinfo
 | 
						|
        if charinfo[property] ~= nil and charinfo[property] == value then
 | 
						|
            return QBCore.Players[src]
 | 
						|
        end
 | 
						|
    end
 | 
						|
    return nil
 | 
						|
end
 | 
						|
 | 
						|
---Get all players. Returns the server ids of all players.
 | 
						|
---@return table
 | 
						|
function QBCore.Functions.GetPlayers()
 | 
						|
    local sources = {}
 | 
						|
    for k in pairs(QBCore.Players) do
 | 
						|
        sources[#sources + 1] = k
 | 
						|
    end
 | 
						|
    return sources
 | 
						|
end
 | 
						|
 | 
						|
---Will return an array of QB Player class instances
 | 
						|
---unlike the GetPlayers() wrapper which only returns IDs
 | 
						|
---@return table
 | 
						|
function QBCore.Functions.GetQBPlayers()
 | 
						|
    return QBCore.Players
 | 
						|
end
 | 
						|
 | 
						|
---Gets a list of all on duty players of a specified job and the number
 | 
						|
---@param job string
 | 
						|
---@return table, number
 | 
						|
function QBCore.Functions.GetPlayersOnDuty(job)
 | 
						|
    local players = {}
 | 
						|
    local count = 0
 | 
						|
    for src, Player in pairs(QBCore.Players) do
 | 
						|
        if Player.PlayerData.job.name == job then
 | 
						|
            if Player.PlayerData.job.onduty then
 | 
						|
                players[#players + 1] = src
 | 
						|
                count += 1
 | 
						|
            end
 | 
						|
        end
 | 
						|
    end
 | 
						|
    return players, count
 | 
						|
end
 | 
						|
 | 
						|
---Returns only the amount of players on duty for the specified job
 | 
						|
---@param job string
 | 
						|
---@return number
 | 
						|
function QBCore.Functions.GetDutyCount(job)
 | 
						|
    local count = 0
 | 
						|
    for _, Player in pairs(QBCore.Players) do
 | 
						|
        if Player.PlayerData.job.name == job then
 | 
						|
            if Player.PlayerData.job.onduty then
 | 
						|
                count += 1
 | 
						|
            end
 | 
						|
        end
 | 
						|
    end
 | 
						|
    return count
 | 
						|
end
 | 
						|
 | 
						|
--- @param source number source player's server ID.
 | 
						|
--- @param coords vector The coordinates to calculate the distance from. Can be a table with x, y, z fields or a vector3. If not provided, the source player's Ped's coordinates are used.
 | 
						|
--- @return string closestPlayer - The Player that is closest to the source player (or the provided coordinates). Returns -1 if no Players are found.
 | 
						|
--- @return number closestDistance - The distance to the closest Player. Returns -1 if no Players are found.
 | 
						|
function QBCore.Functions.GetClosestPlayer(source, coords)
 | 
						|
    local ped = GetPlayerPed(source)
 | 
						|
    local players = GetPlayers()
 | 
						|
    local closestDistance, closestPlayer = -1, -1
 | 
						|
    if coords then coords = type(coords) == 'table' and vector3(coords.x, coords.y, coords.z) or coords end
 | 
						|
    if not coords then coords = GetEntityCoords(ped) end
 | 
						|
    for i = 1, #players do
 | 
						|
        local playerId = players[i]
 | 
						|
        local playerPed = GetPlayerPed(playerId)
 | 
						|
        if playerPed ~= ped then
 | 
						|
            local playerCoords = GetEntityCoords(playerPed)
 | 
						|
            local distance = #(playerCoords - coords)
 | 
						|
            if closestDistance == -1 or distance < closestDistance then
 | 
						|
                closestPlayer = playerId
 | 
						|
                closestDistance = distance
 | 
						|
            end
 | 
						|
        end
 | 
						|
    end
 | 
						|
    return closestPlayer, closestDistance
 | 
						|
end
 | 
						|
 | 
						|
--- @param source number source player's server ID.
 | 
						|
--- @param coords vector The coordinates to calculate the distance from. Can be a table with x, y, z fields or a vector3. If not provided, the source player's Ped's coordinates are used.
 | 
						|
--- @return number closestObject - The Object that is closest to the source player (or the provided coordinates). Returns -1 if no Objects are found.
 | 
						|
--- @return number closestDistance - The distance to the closest Object. Returns -1 if no Objects are found.
 | 
						|
function QBCore.Functions.GetClosestObject(source, coords)
 | 
						|
    local ped = GetPlayerPed(source)
 | 
						|
    local objects = GetAllObjects()
 | 
						|
    local closestDistance, closestObject = -1, -1
 | 
						|
    if coords then coords = type(coords) == 'table' and vector3(coords.x, coords.y, coords.z) or coords end
 | 
						|
    if not coords then coords = GetEntityCoords(ped) end
 | 
						|
    for i = 1, #objects do
 | 
						|
        local objectCoords = GetEntityCoords(objects[i])
 | 
						|
        local distance = #(objectCoords - coords)
 | 
						|
        if closestDistance == -1 or closestDistance > distance then
 | 
						|
            closestObject = objects[i]
 | 
						|
            closestDistance = distance
 | 
						|
        end
 | 
						|
    end
 | 
						|
    return closestObject, closestDistance
 | 
						|
end
 | 
						|
 | 
						|
--- @param source number source player's server ID.
 | 
						|
--- @param coords vector The coordinates to calculate the distance from. Can be a table with x, y, z fields or a vector3. If not provided, the source player's Ped's coordinates are used.
 | 
						|
--- @return number closestVehicle - The Vehicle that is closest to the source player (or the provided coordinates). Returns -1 if no Vehicles are found.
 | 
						|
--- @return number closestDistance - The distance to the closest Vehicle. Returns -1 if no Vehicles are found.
 | 
						|
function QBCore.Functions.GetClosestVehicle(source, coords)
 | 
						|
    local ped = GetPlayerPed(source)
 | 
						|
    local vehicles = GetAllVehicles()
 | 
						|
    local closestDistance, closestVehicle = -1, -1
 | 
						|
    if coords then coords = type(coords) == 'table' and vector3(coords.x, coords.y, coords.z) or coords end
 | 
						|
    if not coords then coords = GetEntityCoords(ped) end
 | 
						|
    for i = 1, #vehicles do
 | 
						|
        local vehicleCoords = GetEntityCoords(vehicles[i])
 | 
						|
        local distance = #(vehicleCoords - coords)
 | 
						|
        if closestDistance == -1 or closestDistance > distance then
 | 
						|
            closestVehicle = vehicles[i]
 | 
						|
            closestDistance = distance
 | 
						|
        end
 | 
						|
    end
 | 
						|
    return closestVehicle, closestDistance
 | 
						|
end
 | 
						|
 | 
						|
--- @param source number source player's server ID.
 | 
						|
--- @param coords vector The coordinates to calculate the distance from. Can be a table with x, y, z fields or a vector3. If not provided, the source player's Ped's coordinates are used.
 | 
						|
--- @return number closestPed - The Ped that is closest to the source player (or the provided coordinates). Returns -1 if no Peds are found.
 | 
						|
--- @return number closestDistance - The distance to the closest Ped. Returns -1 if no Peds are found.
 | 
						|
function QBCore.Functions.GetClosestPed(source, coords)
 | 
						|
    local ped = GetPlayerPed(source)
 | 
						|
    local peds = GetAllPeds()
 | 
						|
    local closestDistance, closestPed = -1, -1
 | 
						|
    if coords then coords = type(coords) == 'table' and vector3(coords.x, coords.y, coords.z) or coords end
 | 
						|
    if not coords then coords = GetEntityCoords(ped) end
 | 
						|
    for i = 1, #peds do
 | 
						|
        if peds[i] ~= ped then
 | 
						|
            local pedCoords = GetEntityCoords(peds[i])
 | 
						|
            local distance = #(pedCoords - coords)
 | 
						|
            if closestDistance == -1 or closestDistance > distance then
 | 
						|
                closestPed = peds[i]
 | 
						|
                closestDistance = distance
 | 
						|
            end
 | 
						|
        end
 | 
						|
    end
 | 
						|
    return closestPed, closestDistance
 | 
						|
end
 | 
						|
 | 
						|
-- Routing buckets (Only touch if you know what you are doing)
 | 
						|
 | 
						|
---Returns the objects related to buckets, first returned value is the player buckets, second one is entity buckets
 | 
						|
---@return table, table
 | 
						|
function QBCore.Functions.GetBucketObjects()
 | 
						|
    return QBCore.Player_Buckets, QBCore.Entity_Buckets
 | 
						|
end
 | 
						|
 | 
						|
---Will set the provided player id / source into the provided bucket id
 | 
						|
---@param source any
 | 
						|
---@param bucket any
 | 
						|
---@return boolean
 | 
						|
function QBCore.Functions.SetPlayerBucket(source, bucket)
 | 
						|
    if source and bucket then
 | 
						|
        local plicense = QBCore.Functions.GetIdentifier(source, 'license')
 | 
						|
        Player(source).state:set('instance', bucket, true)
 | 
						|
        SetPlayerRoutingBucket(source, bucket)
 | 
						|
        QBCore.Player_Buckets[plicense] = { id = source, bucket = bucket }
 | 
						|
        return true
 | 
						|
    else
 | 
						|
        return false
 | 
						|
    end
 | 
						|
end
 | 
						|
 | 
						|
---Will set any entity into the provided bucket, for example peds / vehicles / props / etc.
 | 
						|
---@param entity number
 | 
						|
---@param bucket number
 | 
						|
---@return boolean
 | 
						|
function QBCore.Functions.SetEntityBucket(entity, bucket)
 | 
						|
    if entity and bucket then
 | 
						|
        SetEntityRoutingBucket(entity, bucket)
 | 
						|
        QBCore.Entity_Buckets[entity] = { id = entity, bucket = bucket }
 | 
						|
        return true
 | 
						|
    else
 | 
						|
        return false
 | 
						|
    end
 | 
						|
end
 | 
						|
 | 
						|
---Will return an array of all the player ids inside the current bucket
 | 
						|
---@param bucket number
 | 
						|
---@return table|boolean
 | 
						|
function QBCore.Functions.GetPlayersInBucket(bucket)
 | 
						|
    local curr_bucket_pool = {}
 | 
						|
    if QBCore.Player_Buckets and next(QBCore.Player_Buckets) then
 | 
						|
        for _, v in pairs(QBCore.Player_Buckets) do
 | 
						|
            if v.bucket == bucket then
 | 
						|
                curr_bucket_pool[#curr_bucket_pool + 1] = v.id
 | 
						|
            end
 | 
						|
        end
 | 
						|
        return curr_bucket_pool
 | 
						|
    else
 | 
						|
        return false
 | 
						|
    end
 | 
						|
end
 | 
						|
 | 
						|
---Will return an array of all the entities inside the current bucket
 | 
						|
---(not for player entities, use GetPlayersInBucket for that)
 | 
						|
---@param bucket number
 | 
						|
---@return table|boolean
 | 
						|
function QBCore.Functions.GetEntitiesInBucket(bucket)
 | 
						|
    local curr_bucket_pool = {}
 | 
						|
    if QBCore.Entity_Buckets and next(QBCore.Entity_Buckets) then
 | 
						|
        for _, v in pairs(QBCore.Entity_Buckets) do
 | 
						|
            if v.bucket == bucket then
 | 
						|
                curr_bucket_pool[#curr_bucket_pool + 1] = v.id
 | 
						|
            end
 | 
						|
        end
 | 
						|
        return curr_bucket_pool
 | 
						|
    else
 | 
						|
        return false
 | 
						|
    end
 | 
						|
end
 | 
						|
 | 
						|
---Server side vehicle creation with optional callback
 | 
						|
---the CreateVehicle RPC still uses the client for creation so players must be near
 | 
						|
---@param source any
 | 
						|
---@param model any
 | 
						|
---@param coords vector
 | 
						|
---@param warp boolean
 | 
						|
---@return number
 | 
						|
function QBCore.Functions.SpawnVehicle(source, model, coords, warp)
 | 
						|
    local ped = GetPlayerPed(source)
 | 
						|
    model = type(model) == 'string' and joaat(model) or model
 | 
						|
    if not coords then coords = GetEntityCoords(ped) end
 | 
						|
    local heading = coords.w and coords.w or 0.0
 | 
						|
    local veh = CreateVehicle(model, coords.x, coords.y, coords.z, heading, true, true)
 | 
						|
    while not DoesEntityExist(veh) do Wait(0) end
 | 
						|
    if warp then
 | 
						|
        while GetVehiclePedIsIn(ped) ~= veh do
 | 
						|
            Wait(0)
 | 
						|
            TaskWarpPedIntoVehicle(ped, veh, -1)
 | 
						|
        end
 | 
						|
    end
 | 
						|
    while NetworkGetEntityOwner(veh) ~= source do Wait(0) end
 | 
						|
    return veh
 | 
						|
end
 | 
						|
 | 
						|
---Server side vehicle creation with optional callback
 | 
						|
---the CreateAutomobile native is still experimental but doesn't use client for creation
 | 
						|
---doesn't work for all vehicles!
 | 
						|
---comment
 | 
						|
---@param source any
 | 
						|
---@param model any
 | 
						|
---@param coords vector
 | 
						|
---@param warp boolean
 | 
						|
---@return number
 | 
						|
function QBCore.Functions.CreateAutomobile(source, model, coords, warp)
 | 
						|
    model = type(model) == 'string' and joaat(model) or model
 | 
						|
    if not coords then coords = GetEntityCoords(GetPlayerPed(source)) end
 | 
						|
    local heading = coords.w and coords.w or 0.0
 | 
						|
    local CreateAutomobile = `CREATE_AUTOMOBILE`
 | 
						|
    local veh = Citizen.InvokeNative(CreateAutomobile, model, coords, heading, true, true)
 | 
						|
    while not DoesEntityExist(veh) do Wait(0) end
 | 
						|
    if warp then TaskWarpPedIntoVehicle(GetPlayerPed(source), veh, -1) end
 | 
						|
    return veh
 | 
						|
end
 | 
						|
 | 
						|
--- New & more reliable server side native for creating vehicles
 | 
						|
---comment
 | 
						|
---@param source any
 | 
						|
---@param model any
 | 
						|
---@param vehtype any
 | 
						|
-- The appropriate vehicle type for the model info.
 | 
						|
-- Can be one of automobile, bike, boat, heli, plane, submarine, trailer, and (potentially), train.
 | 
						|
-- This should be the same type as the type field in vehicles.meta.
 | 
						|
---@param coords vector
 | 
						|
---@param warp boolean
 | 
						|
---@return number
 | 
						|
function QBCore.Functions.CreateVehicle(source, model, vehtype, coords, warp)
 | 
						|
    model = type(model) == 'string' and joaat(model) or model
 | 
						|
    vehtype = type(vehtype) == 'string' and tostring(vehtype) or vehtype
 | 
						|
    if not coords then coords = GetEntityCoords(GetPlayerPed(source)) end
 | 
						|
    local heading = coords.w and coords.w or 0.0
 | 
						|
    local veh = CreateVehicleServerSetter(model, vehtype, coords, heading)
 | 
						|
    while not DoesEntityExist(veh) do Wait(0) end
 | 
						|
    if warp then TaskWarpPedIntoVehicle(GetPlayerPed(source), veh, -1) end
 | 
						|
    return veh
 | 
						|
end
 | 
						|
 | 
						|
function PaycheckInterval()
 | 
						|
    if next(QBCore.Players) then
 | 
						|
        for _, Player in pairs(QBCore.Players) do
 | 
						|
            if Player then
 | 
						|
                local payment = Player.PlayerData.job.payment
 | 
						|
                if Player.PlayerData.job and payment > 0 and (QBShared.Jobs[Player.PlayerData.job.name].offDutyPay or Player.PlayerData.job.onduty) then
 | 
						|
                    if QBCore.Config.Money.PayCheckSociety then
 | 
						|
                        local account = exports['qb-management']:GetAccount(Player.PlayerData.job.name)
 | 
						|
                        if account ~= 0 then -- Checks if player is employed by a society
 | 
						|
                            if account < payment then -- Checks if company has enough money to pay society
 | 
						|
                                TriggerClientEvent('QBCore:Notify', Player.PlayerData.source, Lang:t('error.company_too_poor'), 'error')
 | 
						|
                            else
 | 
						|
                                Player.Functions.AddMoney('bank', payment)
 | 
						|
                                exports['qb-management']:RemoveMoney(Player.PlayerData.job.name, payment)
 | 
						|
                                TriggerClientEvent('QBCore:Notify', Player.PlayerData.source, Lang:t('info.received_paycheck', {value = payment}))
 | 
						|
                                TriggerEvent('okokBanking:AddTransferTransactionFromSocietyToP', payment, "salary", "Salary", Player.PlayerData.citizenid, Player.PlayerData.charinfo.firstname..' '..Player.PlayerData.charinfo.lastname)
 | 
						|
                            end
 | 
						|
                        else
 | 
						|
                            Player.Functions.AddMoney('bank', payment)
 | 
						|
                            TriggerClientEvent('QBCore:Notify', Player.PlayerData.source, Lang:t('info.received_paycheck', {value = payment}))
 | 
						|
                            TriggerEvent('okokBanking:AddTransferTransactionFromSocietyToP', payment, "salary", "Salary", Player.PlayerData.citizenid, Player.PlayerData.charinfo.firstname..' '..Player.PlayerData.charinfo.lastname)
 | 
						|
                        end
 | 
						|
                    else
 | 
						|
                        Player.Functions.AddMoney('bank', payment)
 | 
						|
                        TriggerClientEvent('QBCore:Notify', Player.PlayerData.source, Lang:t('info.received_paycheck', {value = payment}))
 | 
						|
                        TriggerEvent('okokBanking:AddTransferTransactionFromSocietyToP', payment, "salary", "Salary", Player.PlayerData.citizenid, Player.PlayerData.charinfo.firstname..' '..Player.PlayerData.charinfo.lastname)
 | 
						|
                    end
 | 
						|
                end
 | 
						|
            end
 | 
						|
        end
 | 
						|
    end
 | 
						|
    SetTimeout(QBCore.Config.Money.PayCheckTimeOut * (60 * 1000), PaycheckInterval)
 | 
						|
end
 | 
						|
 | 
						|
-- Callback Functions --
 | 
						|
 | 
						|
---Trigger Client Callback
 | 
						|
---@param name string
 | 
						|
---@param source any
 | 
						|
---@param cb function
 | 
						|
---@param ... any
 | 
						|
function QBCore.Functions.TriggerClientCallback(name, source, ...)
 | 
						|
    local cb = nil
 | 
						|
    local args = { ... }
 | 
						|
 | 
						|
    if QBCore.Shared.IsFunction(args[1]) then
 | 
						|
        cb = args[1]
 | 
						|
        table.remove(args, 1)
 | 
						|
    end
 | 
						|
 | 
						|
    QBCore.ClientCallbacks[name] = {
 | 
						|
        callback = cb,
 | 
						|
        promise = promise.new()
 | 
						|
    }
 | 
						|
 | 
						|
    TriggerClientEvent('QBCore:Client:TriggerClientCallback', source, name, table.unpack(args))
 | 
						|
 | 
						|
    if cb == nil then
 | 
						|
        Citizen.Await(QBCore.ClientCallbacks[name].promise)
 | 
						|
        return QBCore.ClientCallbacks[name].promise.value
 | 
						|
    end
 | 
						|
end
 | 
						|
 | 
						|
---Create Server Callback
 | 
						|
---@param name string
 | 
						|
---@param cb function
 | 
						|
function QBCore.Functions.CreateCallback(name, cb)
 | 
						|
    QBCore.ServerCallbacks[name] = cb
 | 
						|
end
 | 
						|
 | 
						|
-- Items
 | 
						|
 | 
						|
---Create a usable item
 | 
						|
---@param item string
 | 
						|
---@param data function
 | 
						|
function QBCore.Functions.CreateUseableItem(item, data)
 | 
						|
    QBCore.UsableItems[item] = data
 | 
						|
end
 | 
						|
 | 
						|
---Checks if the given item is usable
 | 
						|
---@param item string
 | 
						|
---@return any
 | 
						|
function QBCore.Functions.CanUseItem(item)
 | 
						|
    return QBCore.UsableItems[item]
 | 
						|
end
 | 
						|
 | 
						|
---Use item
 | 
						|
---@param source any
 | 
						|
---@param item string
 | 
						|
function QBCore.Functions.UseItem(source, item)
 | 
						|
    if GetResourceState('qs-inventory') == 'missing' then return end
 | 
						|
    exports['qs-inventory']:UseItem(source, item)
 | 
						|
end
 | 
						|
 | 
						|
---Kick Player
 | 
						|
---@param source any
 | 
						|
---@param reason string
 | 
						|
---@param setKickReason boolean
 | 
						|
---@param deferrals boolean
 | 
						|
function QBCore.Functions.Kick(source, reason, setKickReason, deferrals)
 | 
						|
    reason = '\n' .. reason .. '\n🔸 Check our Discord for further information: ' .. QBCore.Config.Server.Discord
 | 
						|
    if setKickReason then
 | 
						|
        setKickReason(reason)
 | 
						|
    end
 | 
						|
    CreateThread(function()
 | 
						|
        if deferrals then
 | 
						|
            deferrals.update(reason)
 | 
						|
            Wait(2500)
 | 
						|
        end
 | 
						|
        if source then
 | 
						|
            DropPlayer(source, reason)
 | 
						|
        end
 | 
						|
        for _ = 0, 4 do
 | 
						|
            while true do
 | 
						|
                if source then
 | 
						|
                    if GetPlayerPing(source) >= 0 then
 | 
						|
                        break
 | 
						|
                    end
 | 
						|
                    Wait(100)
 | 
						|
                    CreateThread(function()
 | 
						|
                        DropPlayer(source, reason)
 | 
						|
                    end)
 | 
						|
                end
 | 
						|
            end
 | 
						|
            Wait(5000)
 | 
						|
        end
 | 
						|
    end)
 | 
						|
end
 | 
						|
 | 
						|
---Check if player is whitelisted, kept like this for backwards compatibility or future plans
 | 
						|
---@param source any
 | 
						|
---@return boolean
 | 
						|
function QBCore.Functions.IsWhitelisted(source)
 | 
						|
    if not QBCore.Config.Server.Whitelist then return true end
 | 
						|
    if QBCore.Functions.HasPermission(source, QBCore.Config.Server.WhitelistPermission) then return true end
 | 
						|
    return false
 | 
						|
end
 | 
						|
 | 
						|
-- Setting & Removing Permissions
 | 
						|
 | 
						|
---Add permission for player
 | 
						|
---@param source any
 | 
						|
---@param permission string
 | 
						|
function QBCore.Functions.AddPermission(source, permission)
 | 
						|
    if not IsPlayerAceAllowed(source, permission) then
 | 
						|
        ExecuteCommand(('add_principal player.%s qbcore.%s'):format(source, permission))
 | 
						|
        QBCore.Commands.Refresh(source)
 | 
						|
    end
 | 
						|
end
 | 
						|
 | 
						|
---Remove permission from player
 | 
						|
---@param source any
 | 
						|
---@param permission string
 | 
						|
function QBCore.Functions.RemovePermission(source, permission)
 | 
						|
    if permission then
 | 
						|
        if IsPlayerAceAllowed(source, permission) then
 | 
						|
            ExecuteCommand(('remove_principal player.%s qbcore.%s'):format(source, permission))
 | 
						|
            QBCore.Commands.Refresh(source)
 | 
						|
        end
 | 
						|
    else
 | 
						|
        for _, v in pairs(QBCore.Config.Server.Permissions) do
 | 
						|
            if IsPlayerAceAllowed(source, v) then
 | 
						|
                ExecuteCommand(('remove_principal player.%s qbcore.%s'):format(source, v))
 | 
						|
                QBCore.Commands.Refresh(source)
 | 
						|
            end
 | 
						|
        end
 | 
						|
    end
 | 
						|
end
 | 
						|
 | 
						|
-- Checking for Permission Level
 | 
						|
 | 
						|
---Check if player has permission
 | 
						|
---@param source any
 | 
						|
---@param permission string
 | 
						|
---@return boolean
 | 
						|
function QBCore.Functions.HasPermission(source, permission)
 | 
						|
    if type(permission) == 'string' then
 | 
						|
        if IsPlayerAceAllowed(source, permission) then return true end
 | 
						|
    elseif type(permission) == 'table' then
 | 
						|
        for _, permLevel in pairs(permission) do
 | 
						|
            if IsPlayerAceAllowed(source, permLevel) then return true end
 | 
						|
        end
 | 
						|
    end
 | 
						|
 | 
						|
    return false
 | 
						|
end
 | 
						|
 | 
						|
---Get the players permissions
 | 
						|
---@param source any
 | 
						|
---@return table
 | 
						|
function QBCore.Functions.GetPermission(source)
 | 
						|
    local src = source
 | 
						|
    local perms = {}
 | 
						|
    for _, v in pairs(QBCore.Config.Server.Permissions) do
 | 
						|
        if IsPlayerAceAllowed(src, v) then
 | 
						|
            perms[v] = true
 | 
						|
        end
 | 
						|
    end
 | 
						|
    return perms
 | 
						|
end
 | 
						|
 | 
						|
---Get admin messages opt-in state for player
 | 
						|
---@param source any
 | 
						|
---@return boolean
 | 
						|
function QBCore.Functions.IsOptin(source)
 | 
						|
    local license = QBCore.Functions.GetIdentifier(source, 'license')
 | 
						|
    if not license or not QBCore.Functions.HasPermission(source, 'admin') then return false end
 | 
						|
    local Player = QBCore.Functions.GetPlayer(source)
 | 
						|
    return Player.PlayerData.optin
 | 
						|
end
 | 
						|
 | 
						|
---Toggle opt-in to admin messages
 | 
						|
---@param source any
 | 
						|
function QBCore.Functions.ToggleOptin(source)
 | 
						|
    local license = QBCore.Functions.GetIdentifier(source, 'license')
 | 
						|
    if not license or not QBCore.Functions.HasPermission(source, 'admin') then return end
 | 
						|
    local Player = QBCore.Functions.GetPlayer(source)
 | 
						|
    Player.PlayerData.optin = not Player.PlayerData.optin
 | 
						|
    Player.Functions.SetPlayerData('optin', Player.PlayerData.optin)
 | 
						|
end
 | 
						|
 | 
						|
---Check if player is banned
 | 
						|
---@param source any
 | 
						|
---@return boolean, string?
 | 
						|
function QBCore.Functions.IsPlayerBanned(source)
 | 
						|
    local plicense = QBCore.Functions.GetIdentifier(source, 'license')
 | 
						|
    local result = MySQL.single.await('SELECT id, reason, expire FROM bans WHERE license = ?', { plicense })
 | 
						|
    if not result then return false end
 | 
						|
    if os.time() < result.expire then
 | 
						|
        local timeTable = os.date('*t', tonumber(result.expire))
 | 
						|
        return true, 'You have been banned from the server:\n' .. result.reason .. '\nYour ban expires ' .. timeTable.day .. '/' .. timeTable.month .. '/' .. timeTable.year .. ' ' .. timeTable.hour .. ':' .. timeTable.min .. '\n'
 | 
						|
    else
 | 
						|
        MySQL.query('DELETE FROM bans WHERE id = ?', { result.id })
 | 
						|
    end
 | 
						|
    return false
 | 
						|
end
 | 
						|
 | 
						|
-- Retrieves information about the database connection.
 | 
						|
--- @return table; A table containing the database information.
 | 
						|
function QBCore.Functions.GetDatabaseInfo()
 | 
						|
    local details = {
 | 
						|
        exists = false,
 | 
						|
        database = '',
 | 
						|
    }
 | 
						|
    local connectionString = GetConvar('mysql_connection_string', '')
 | 
						|
 | 
						|
    if connectionString == '' then
 | 
						|
        return details
 | 
						|
    elseif connectionString:find('mysql://') then
 | 
						|
        connectionString = connectionString:sub(9, -1)
 | 
						|
        details.database = connectionString:sub(connectionString:find('/') + 1, -1):gsub('[%?]+[%w%p]*$', '')
 | 
						|
        details.exists = true
 | 
						|
        return details
 | 
						|
    else
 | 
						|
        connectionString = { string.strsplit(';', connectionString) }
 | 
						|
 | 
						|
        for i = 1, #connectionString do
 | 
						|
            local v = connectionString[i]
 | 
						|
            if v:match('database') then
 | 
						|
                details.database = v:sub(10, #v)
 | 
						|
                details.exists = true
 | 
						|
                return details
 | 
						|
            end
 | 
						|
        end
 | 
						|
    end
 | 
						|
end
 | 
						|
 | 
						|
---Check for duplicate license
 | 
						|
---@param license any
 | 
						|
---@return boolean
 | 
						|
function QBCore.Functions.IsLicenseInUse(license)
 | 
						|
    local players = GetPlayers()
 | 
						|
    for _, player in pairs(players) do
 | 
						|
        local playerLicense = QBCore.Functions.GetIdentifier(player, 'license')
 | 
						|
        if playerLicense == license then return true end
 | 
						|
    end
 | 
						|
    return false
 | 
						|
end
 | 
						|
 | 
						|
-- Utility functions
 | 
						|
 | 
						|
---Check if a player has an item [deprecated]
 | 
						|
---@param source any
 | 
						|
---@param items table|string
 | 
						|
---@param amount number
 | 
						|
---@return boolean
 | 
						|
function QBCore.Functions.HasItem(source, items, amount)
 | 
						|
    if GetResourceState('qs-inventory') == 'missing' then return end
 | 
						|
    return exports['qs-inventory']:HasItem(source, items, amount)
 | 
						|
end
 | 
						|
 | 
						|
---Notify
 | 
						|
---@param source any
 | 
						|
---@param text string
 | 
						|
---@param type string
 | 
						|
---@param length number
 | 
						|
function QBCore.Functions.Notify(source, text, type, length)
 | 
						|
    TriggerClientEvent('QBCore:Notify', source, text, type, length)
 | 
						|
end
 | 
						|
 | 
						|
---???? ... ok
 | 
						|
---@param source any
 | 
						|
---@param data any
 | 
						|
---@param pattern any
 | 
						|
---@return boolean
 | 
						|
function QBCore.Functions.PrepForSQL(source, data, pattern)
 | 
						|
    data = tostring(data)
 | 
						|
    local src = source
 | 
						|
    local player = QBCore.Functions.GetPlayer(src)
 | 
						|
    local result = string.match(data, pattern)
 | 
						|
    if not result or string.len(result) ~= string.len(data) then
 | 
						|
        TriggerEvent('qb-log:server:CreateLog', 'anticheat', 'SQL Exploit Attempted', 'red', string.format('%s attempted to exploit SQL!', player.PlayerData.license))
 | 
						|
        return false
 | 
						|
    end
 | 
						|
    return true
 | 
						|
end
 | 
						|
 | 
						|
for functionName, func in pairs(QBCore.Functions) do
 | 
						|
    if type(func) == 'function' then
 | 
						|
        exports(functionName, func)
 | 
						|
    end
 | 
						|
end
 | 
						|
 | 
						|
-- Access a specific function directly:
 | 
						|
-- exports['qb-core']:Notify(source, 'Hello Player!')
 |