ed
This commit is contained in:
		
							parent
							
								
									510e3ffcf2
								
							
						
					
					
						commit
						f43cf424cf
					
				
					 305 changed files with 34683 additions and 0 deletions
				
			
		| 
						 | 
				
			
			@ -0,0 +1,24 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
BossMenu = BossMenu or {}
 | 
			
		||||
 | 
			
		||||
---This will get the name of the module being used.
 | 
			
		||||
---@return string
 | 
			
		||||
BossMenu.GetResourceName = function()
 | 
			
		||||
    return "default"
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
RegisterNetEvent('community_bridge:client:OpenBossMenu', function(jobName, jobType)
 | 
			
		||||
    -- these systems seem to do the verification for isboss themselves, so we don't need to check if the player is a boss.
 | 
			
		||||
    -- also this source check is to ensure that the event is only triggered by the server.
 | 
			
		||||
    if source ~= 65535 then return end
 | 
			
		||||
    if BossMenu.GetResourceName() == "esx_society" then
 | 
			
		||||
        local ESX = exports["es_extended"]:getSharedObject() -- better solution needed but fuck it for now.
 | 
			
		||||
        TriggerEvent('esx_society:openBossMenu', jobName, function(menu)
 | 
			
		||||
            ESX.CloseContext()
 | 
			
		||||
        end, {wash = false})
 | 
			
		||||
    elseif BossMenu.GetResourceName() == "qbx_management" then
 | 
			
		||||
        exports.qbx_management:OpenBossMenu(jobType)
 | 
			
		||||
    end
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
return BossMenu
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,14 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
BossMenu = BossMenu or {}
 | 
			
		||||
 | 
			
		||||
---This will get the name of the module being used.
 | 
			
		||||
---@return string
 | 
			
		||||
BossMenu.GetResourceName = function()
 | 
			
		||||
    return "default"
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
BossMenu.OpenBossMenu = function(src, jobName, jobType)
 | 
			
		||||
    print("You are using the community_bridge module for boss menus. Please ensure you have the correct dependencies installed.")
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return BossMenu
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,12 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
if GetResourceState('esx_society') ~= 'started' then return end
 | 
			
		||||
 | 
			
		||||
BossMenu = BossMenu or {}
 | 
			
		||||
 | 
			
		||||
---This will get the name of the module being used.
 | 
			
		||||
---@return string
 | 
			
		||||
BossMenu.GetResourceName = function()
 | 
			
		||||
    return "esx_society"
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return BossMenu
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,21 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
if GetResourceState('esx_society') ~= 'started' then return end
 | 
			
		||||
 | 
			
		||||
BossMenu = BossMenu or {}
 | 
			
		||||
 | 
			
		||||
---This will get the name of the module being used.
 | 
			
		||||
---@return string
 | 
			
		||||
BossMenu.GetResourceName = function()
 | 
			
		||||
    return "esx_society"
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local registeredSocieties = {}
 | 
			
		||||
BossMenu.OpenBossMenu = function(src, jobName, jobType)
 | 
			
		||||
    if not registeredSocieties[jobName] then
 | 
			
		||||
        exports["esx_society"]:registerSociety(jobName, jobName, 'society_' .. jobName, 'society_' .. jobName, 'society_' .. jobName, {type = 'private'})
 | 
			
		||||
        registeredSocieties[jobName] = true
 | 
			
		||||
    end
 | 
			
		||||
    TriggerClientEvent("community_bridge:client:OpenBossMenu", src, jobName, jobType)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return BossMenu
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,13 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
if GetResourceState('qb-management') ~= 'started' then return end
 | 
			
		||||
if GetResourceState('qbx_management') == 'started' then return end
 | 
			
		||||
 | 
			
		||||
BossMenu = BossMenu or {}
 | 
			
		||||
 | 
			
		||||
---This will get the name of the module being used.
 | 
			
		||||
---@return string
 | 
			
		||||
BossMenu.GetResourceName = function()
 | 
			
		||||
    return "qb-management"
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return BossMenu
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,17 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
if GetResourceState('qb-management') ~= 'started' then return end
 | 
			
		||||
if GetResourceState('qbx_management') == 'started' then return end
 | 
			
		||||
 | 
			
		||||
BossMenu = BossMenu or {}
 | 
			
		||||
 | 
			
		||||
---This will get the name of the module being used.
 | 
			
		||||
---@return string
 | 
			
		||||
BossMenu.GetResourceName = function()
 | 
			
		||||
    return "qb-management"
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
BossMenu.OpenBossMenu = function(src, jobName, jobType)
 | 
			
		||||
    TriggerClientEvent("qb-bossmenu:client:OpenMenu", src)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return BossMenu
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,12 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
if GetResourceState('qbx_management') ~= 'started' then return end
 | 
			
		||||
 | 
			
		||||
BossMenu = BossMenu or {}
 | 
			
		||||
 | 
			
		||||
---This will get the name of the module being used.
 | 
			
		||||
---@return string
 | 
			
		||||
BossMenu.GetResourceName = function()
 | 
			
		||||
    return "qbx_management"
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return BossMenu
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,16 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
if GetResourceState('qbx_management') ~= 'started' then return end
 | 
			
		||||
 | 
			
		||||
BossMenu = BossMenu or {}
 | 
			
		||||
 | 
			
		||||
---This will get the name of the module being used.
 | 
			
		||||
---@return string
 | 
			
		||||
BossMenu.GetResourceName = function()
 | 
			
		||||
    return "qbx_management"
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
BossMenu.OpenBossMenu = function(src, jobName, jobType)
 | 
			
		||||
    TriggerClientEvent("community_bridge:client:OpenBossMenu", src, jobName, jobType)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return BossMenu
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,150 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
Clothing = Clothing or {}
 | 
			
		||||
 | 
			
		||||
ClothingBackup = {}
 | 
			
		||||
Callback = Callback or Require("lib/utility/shared/callbacks.lua")
 | 
			
		||||
Ultility = Utility or Require('lib/utility/client/utility.lua')
 | 
			
		||||
Cache = Cache or Require('lib/cache/shared/cache.lua')
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function Clothing.IsMale()
 | 
			
		||||
    local ped = PlayerPedId()
 | 
			
		||||
    if not ped then return end
 | 
			
		||||
    if GetEntityModel(ped) == `mp_m_freemode_01` then
 | 
			
		||||
        return true
 | 
			
		||||
    end
 | 
			
		||||
    return false
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Get the skin data of a ped
 | 
			
		||||
---@param entity number
 | 
			
		||||
---@return table
 | 
			
		||||
function Clothing.GetAppearance(entity)
 | 
			
		||||
    if not entity and not DoesEntityExist(entity) then return end
 | 
			
		||||
    local model = GetEntityModel(entity)
 | 
			
		||||
    local skinData = { model = model, components = {}, props = {} }
 | 
			
		||||
    for i = 0, 11 do
 | 
			
		||||
        table.insert(skinData.components,
 | 
			
		||||
            { component_id = i, drawable = GetPedDrawableVariation(entity, i), texture = GetPedTextureVariation(entity, i) })
 | 
			
		||||
    end
 | 
			
		||||
    for i = 0, 13 do
 | 
			
		||||
        table.insert(skinData.props,
 | 
			
		||||
            { prop_id = i, drawable = GetPedPropIndex(entity, i), texture = GetPedPropTextureIndex(entity, i) })
 | 
			
		||||
    end
 | 
			
		||||
    return skinData
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function Clothing.CopyAppearanceToClipboard()
 | 
			
		||||
    local ped = PlayerPedId()
 | 
			
		||||
    if not ped or not DoesEntityExist(ped) then return end
 | 
			
		||||
    local skinData = Clothing.GetAppearance(ped)
 | 
			
		||||
    if not skinData then return end
 | 
			
		||||
    Ultility.CopyToClipboard(skinData)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
Callback.Register('community_bridge:cb:GetAppearance', function()
 | 
			
		||||
    local ped = PlayerPedId()
 | 
			
		||||
    if not ped or not DoesEntityExist(ped) then return end
 | 
			
		||||
    local skinData = Clothing.GetAppearance(ped)
 | 
			
		||||
    return skinData
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
---Apply skin data to a ped
 | 
			
		||||
---@param entity number
 | 
			
		||||
---@param skinData table
 | 
			
		||||
---@return boolean
 | 
			
		||||
function Clothing.SetAppearance(entity, skinData)
 | 
			
		||||
    for k, v in pairs(skinData.components or {}) do
 | 
			
		||||
        if v.component_id then
 | 
			
		||||
            SetPedComponentVariation(entity, v.component_id, v.drawable, v.texture, 0)
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
    for k, v in pairs(skinData.props or {}) do
 | 
			
		||||
        if v.prop_id then
 | 
			
		||||
            SetPedPropIndex(entity, v.prop_id, v.drawable, v.texture, 0)
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
    return true
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return the peds components to the previously stored components
 | 
			
		||||
---@return boolean
 | 
			
		||||
Clothing.RestoreAppearance = function(entity)
 | 
			
		||||
    Clothing.SetAppearance(entity, ClothingBackup)
 | 
			
		||||
    return true
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
Clothing.UpdateAppearanceBackup = function(data)
 | 
			
		||||
    ClothingBackup = data
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
Clothing.RunningDebug = false
 | 
			
		||||
Clothing.Cache = nil -- maybe change this to the actual cache system???!? For future not lazy me
 | 
			
		||||
 | 
			
		||||
Cache.Create('Clothing', function()
 | 
			
		||||
    local ped = Cache.Get('Ped')
 | 
			
		||||
    local appearance = Clothing.GetAppearance(ped)
 | 
			
		||||
    if Table.Compare(Clothing.Cache, appearance) then
 | 
			
		||||
        return false
 | 
			
		||||
    end
 | 
			
		||||
    return appearance
 | 
			
		||||
end, 1000)
 | 
			
		||||
 | 
			
		||||
local onChange = nil
 | 
			
		||||
Clothing.ToggleDebugging = function()
 | 
			
		||||
    if Clothing.RunningDebug then
 | 
			
		||||
        Clothing.RunningDebug = false
 | 
			
		||||
        print("Clothing Debugging Disabled")
 | 
			
		||||
        return Cache.RemoveOnChange('Clothing', onChange)
 | 
			
		||||
    end
 | 
			
		||||
    Clothing.RunningDebug = true
 | 
			
		||||
    print("Clothing Debugging Enabled")
 | 
			
		||||
 | 
			
		||||
    if Clothing.OpenMenu then
 | 
			
		||||
        Clothing.OpenMenu()
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    onChange = Cache.OnChange('Clothing', function(new, old)
 | 
			
		||||
        print("Clothing Debugging", new)
 | 
			
		||||
        for k, v in pairs(old.components) do
 | 
			
		||||
            if v.component_id then
 | 
			
		||||
                if new.components[k].drawable ~= v.drawable or new.components[k].texture ~= v.texture then
 | 
			
		||||
                    print("Component ID: " ..
 | 
			
		||||
                    v.component_id ..
 | 
			
		||||
                    " Drawable: " .. new.components[k].drawable .. " Texture: " .. new.components[k].texture)
 | 
			
		||||
                end
 | 
			
		||||
            end
 | 
			
		||||
        end
 | 
			
		||||
        for k, v in pairs(old.props) do
 | 
			
		||||
            if v.prop_id then
 | 
			
		||||
                if new.props[k].drawable ~= v.drawable or new.props[k].texture ~= v.texture then
 | 
			
		||||
                    print("Prop ID: " ..
 | 
			
		||||
                    v.prop_id .. " Drawable: " .. new.props[k].drawable .. " Texture: " .. new.props[k].texture)
 | 
			
		||||
                end
 | 
			
		||||
            end
 | 
			
		||||
        end
 | 
			
		||||
    end)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
RegisterNetEvent('community_bridge:client:SetAppearance', function(data)
 | 
			
		||||
    Clothing.SetAppearance(PlayerPedId(), data)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
RegisterNetEvent('community_bridge:client:GetAppearance', function()
 | 
			
		||||
    Clothing.GetAppearance(PlayerPedId())
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
RegisterNetEvent('community_bridge:client:RestoreAppearance', function()
 | 
			
		||||
    Clothing.RestoreAppearance(PlayerPedId())
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
-- RegisterCommand("clothing:enabledebug", function(source, args, rawCommand)
 | 
			
		||||
--     Clothing.ToggleDebugging()
 | 
			
		||||
-- end)
 | 
			
		||||
 | 
			
		||||
-- RegisterCommand("clothing:copy", function(source, args, rawCommand)
 | 
			
		||||
--     Clothing.CopyAppearanceToClipboard()
 | 
			
		||||
-- end)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
return Clothing
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,56 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
Clothing = Clothing or {}
 | 
			
		||||
Clothing.LastAppearance = Clothing.LastAppearance or {}
 | 
			
		||||
Callback = Callback or Require("lib/utility/shared/callbacks.lua")
 | 
			
		||||
 | 
			
		||||
function Clothing.IsMale(src)
 | 
			
		||||
    local ped = GetPlayerPed(src)
 | 
			
		||||
    if not ped or not DoesEntityExist(ped) then return end
 | 
			
		||||
    return GetEntityModel(ped) == `mp_m_freemode_01`
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function Clothing.GetAppearance(src)
 | 
			
		||||
    return Callback.Trigger('community_bridge:cb:GetAppearance', src)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
Clothing.SetAppearance = function(src, data)
 | 
			
		||||
    local strSrc = tostring(src)
 | 
			
		||||
    Clothing.LastAppearance[strSrc] = Clothing.GetAppearance(src)
 | 
			
		||||
    TriggerClientEvent('community_bridge:client:SetAppearance', src, data)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
--- Sets a player's appearance based on gender-specific data
 | 
			
		||||
---@param src number The server ID of the player
 | 
			
		||||
---@param data table Table containing separate appearance data for male and female characters
 | 
			
		||||
---@return table|nil Appearance updated player appearance data or nil if failed
 | 
			
		||||
function Clothing.SetAppearanceExt(src, data)
 | 
			
		||||
    local tbl = Clothing.IsMale(src) and data.male or data.female
 | 
			
		||||
    Clothing.SetAppearance(src, tbl)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
Clothing.RestoreAppearance = function(src)
 | 
			
		||||
    TriggerClientEvent('community_bridge:client:RestoreAppearance', src)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
-- RegisterNetEvent('community_bridge:client:SetAppearance', function(data)
 | 
			
		||||
--     local src = source
 | 
			
		||||
--     Clothing.SetAppearance(src, data)
 | 
			
		||||
-- end)
 | 
			
		||||
 | 
			
		||||
-- RegisterNetEvent('community_bridge:client:GetAppearance', function()
 | 
			
		||||
--     local src = source
 | 
			
		||||
--     Clothing.GetAppearance(src)
 | 
			
		||||
-- end)
 | 
			
		||||
 | 
			
		||||
-- RegisterNetEvent('community_bridge:client:RestoreAppearance', function()
 | 
			
		||||
--     local src = source
 | 
			
		||||
--     Clothing.RestoreAppearance(src)
 | 
			
		||||
-- end)
 | 
			
		||||
 | 
			
		||||
-- RegisterNetEvent('community_bridge:client:ReloadSkin', function()
 | 
			
		||||
--     local src = source
 | 
			
		||||
--     Clothing.ReloadSkin(src)
 | 
			
		||||
-- end)
 | 
			
		||||
 | 
			
		||||
return Clothing
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,8 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
if GetResourceState('esx_skin') == 'missing' then return end
 | 
			
		||||
if GetResourceState('rcore_clothing') ~= 'missing' then return end
 | 
			
		||||
Clothing = Clothing or {}
 | 
			
		||||
 | 
			
		||||
function Clothing.OpenMenu()
 | 
			
		||||
    TriggerEvent('esx_skin:openMenu', function() end, function() end, true)
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,177 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
if GetResourceState('esx_skin') == 'missing' then return end
 | 
			
		||||
if GetResourceState('rcore_clothing') ~= 'missing' then return end
 | 
			
		||||
Clothing = Clothing or {}
 | 
			
		||||
Clothing.Players = {}
 | 
			
		||||
 | 
			
		||||
Callback = Callback or Require("lib/utility/shared/callbacks.lua")
 | 
			
		||||
Table = Table or Require('lib/utility/shared/tables.lua')
 | 
			
		||||
 | 
			
		||||
---Internal function to get the full appearance data including skin, model, and converted format
 | 
			
		||||
---@param src number The server ID of the player
 | 
			
		||||
---@return table|nil The player's full appearance data or nil if not found
 | 
			
		||||
function Clothing.GetFullAppearanceData(src)
 | 
			
		||||
    src = src and tonumber(src)
 | 
			
		||||
    assert(src, "src is nil")
 | 
			
		||||
    local citId = Bridge.Framework.GetPlayerIdentifier(src)
 | 
			
		||||
    if not citId then return end
 | 
			
		||||
 | 
			
		||||
    if Clothing.Players[citId] then return Clothing.Players[citId] end
 | 
			
		||||
 | 
			
		||||
    local result = MySQL.query.await('SELECT skin FROM users WHERE identifier = ?', { citId })
 | 
			
		||||
    if result[1] == nil then return end
 | 
			
		||||
 | 
			
		||||
    local model = GetEntityModel(GetPlayerPed(src))
 | 
			
		||||
    local skinData = json.decode(result[1].skin)
 | 
			
		||||
    local converted = Clothing.ConvertToDefault(skinData)
 | 
			
		||||
 | 
			
		||||
    -- Store complete data in the cache
 | 
			
		||||
    Clothing.Players[citId] = {
 | 
			
		||||
        model = model,
 | 
			
		||||
        skin = skinData,
 | 
			
		||||
        converted = converted
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return Clothing.Players[citId]
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Retrieves a player's converted appearance data for easy use across modules
 | 
			
		||||
---@param src number The server ID of the player
 | 
			
		||||
---@param fullData boolean Optional - If true, returns the full data object including skin and model
 | 
			
		||||
---@return table|nil The player's converted appearance data or full appearance data if fullData=true
 | 
			
		||||
function Clothing.GetAppearance(src, fullData)
 | 
			
		||||
    if fullData then
 | 
			
		||||
        return Clothing.GetFullAppearanceData(src)
 | 
			
		||||
    end
 | 
			
		||||
    local completeData = Clothing.GetFullAppearanceData(src)
 | 
			
		||||
    if not completeData then return nil end
 | 
			
		||||
    return completeData.converted
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will save the player's current appearance to the database
 | 
			
		||||
---@param src number|string
 | 
			
		||||
function Clothing.Save(src)
 | 
			
		||||
    src = src and tonumber(src)
 | 
			
		||||
    assert(src, "src is nil")
 | 
			
		||||
    local citId = Bridge.Framework.GetPlayerIdentifier(src)
 | 
			
		||||
    if not citId then return end
 | 
			
		||||
    local currentClothing = Clothing.GetFullAppearanceData(src)
 | 
			
		||||
    if not currentClothing then return end
 | 
			
		||||
    local currentSkin = currentClothing.skin
 | 
			
		||||
    local encodedSkin = json.encode(currentSkin)
 | 
			
		||||
    MySQL.update.await('UPDATE users SET skin = ? WHERE identifier = ?', {
 | 
			
		||||
        encodedSkin,
 | 
			
		||||
        citId
 | 
			
		||||
    })
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Sets a player's appearance based on the provided data
 | 
			
		||||
---@param src number The server ID of the player
 | 
			
		||||
---@param data table The appearance data to apply
 | 
			
		||||
---@param updateBackup boolean Whether to update the backup appearance data
 | 
			
		||||
---@return table|nil The updated player appearance data or nil if failed
 | 
			
		||||
function Clothing.SetAppearance(src, data, updateBackup, save)
 | 
			
		||||
    src = src and tonumber(src)
 | 
			
		||||
    assert(src, "src is nil")
 | 
			
		||||
    local citId = Bridge.Framework.GetPlayerIdentifier(src)
 | 
			
		||||
    if not citId then return end
 | 
			
		||||
    local model = GetEntityModel(GetPlayerPed(src))
 | 
			
		||||
    if not model then return end
 | 
			
		||||
    local converted = Clothing.ConvertFromDefault(data)
 | 
			
		||||
 | 
			
		||||
    -- Get full appearance data
 | 
			
		||||
    local currentClothing = Clothing.GetFullAppearanceData(src)
 | 
			
		||||
    if not currentClothing then return end
 | 
			
		||||
 | 
			
		||||
    local currentSkin = currentClothing.skin
 | 
			
		||||
    for k, v in pairs(converted) do
 | 
			
		||||
        currentSkin[k] = v
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    if not Clothing.Players[citId].backup or updateBackup then
 | 
			
		||||
        Clothing.Players[citId].backup = currentClothing.converted
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    Clothing.Players[citId] = Clothing.Players[citId] or {}
 | 
			
		||||
    Clothing.Players[citId].skin = currentSkin
 | 
			
		||||
    Clothing.Players[citId].model = model
 | 
			
		||||
    Clothing.Players[citId].converted = Clothing.ConvertToDefault(currentSkin)
 | 
			
		||||
    if save then
 | 
			
		||||
        local encodedSkin = json.encode(currentSkin)
 | 
			
		||||
        -- saving 1 sql call by adding the query here instead of calling save
 | 
			
		||||
        MySQL.update.await('UPDATE users SET skin = ? WHERE identifier = ?', {
 | 
			
		||||
            encodedSkin,
 | 
			
		||||
            citId
 | 
			
		||||
        })
 | 
			
		||||
    end
 | 
			
		||||
    TriggerClientEvent('community_bridge:client:SetAppearance', src, Clothing.Players[citId].converted)
 | 
			
		||||
    return Clothing.Players[citId]
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
--- Sets a player's appearance based on gender-specific data
 | 
			
		||||
---@param src number The server ID of the player
 | 
			
		||||
---@param data table Table containing separate appearance data for male and female characters
 | 
			
		||||
---@return table|nil Appearance updated player appearance data or nil if failed
 | 
			
		||||
function Clothing.SetAppearanceExt(src, data)
 | 
			
		||||
    local tbl = Clothing.IsMale(src) and data.male or data.female
 | 
			
		||||
    Clothing.SetAppearance(src, tbl)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Reverts a player's appearance to their backup appearance
 | 
			
		||||
---@param src number The server ID of the player
 | 
			
		||||
---@return boolean|nil Returns true if successful or nil if failed
 | 
			
		||||
function Clothing.Revert(src)
 | 
			
		||||
    src = src and tonumber(src)
 | 
			
		||||
    assert(src, "src is nil")
 | 
			
		||||
    local currentClothing = Clothing.GetFullAppearanceData(src)
 | 
			
		||||
    if not currentClothing then return end
 | 
			
		||||
    local backup = currentClothing.backup
 | 
			
		||||
    if not backup then return end
 | 
			
		||||
    return Clothing.SetAppearance(src, backup)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will open the menu for the passed src
 | 
			
		||||
---@param src number|string
 | 
			
		||||
function Clothing.OpenMenu(src)
 | 
			
		||||
    src = src and tonumber(src)
 | 
			
		||||
    assert(src, "src is nil")
 | 
			
		||||
    TriggerClientEvent('esx_skin:openMenu', src)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Event handler for when a player loads into the server
 | 
			
		||||
---Caches the player's appearance data
 | 
			
		||||
AddEventHandler('community_bridge:Server:OnPlayerLoaded', function(src)
 | 
			
		||||
    src = src and tonumber(src)
 | 
			
		||||
    assert(src, "src is nil")
 | 
			
		||||
    -- Use GetFullAppearanceData to cache the complete appearance
 | 
			
		||||
    Clothing.GetFullAppearanceData(src)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
---Event handler for when a player disconnects from the server
 | 
			
		||||
---Removes the player's appearance data from the cache
 | 
			
		||||
AddEventHandler('community_bridge:Server:OnPlayerUnload', function(src)
 | 
			
		||||
    src = src and tonumber(src)
 | 
			
		||||
    assert(src, "src is nil")
 | 
			
		||||
    local strSrc = tostring(src)
 | 
			
		||||
    Clothing.Players[strSrc] = nil
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
---Event handler for when the resource starts
 | 
			
		||||
---Caches appearance data for all currently connected players
 | 
			
		||||
AddEventHandler('onResourceStart', function(resource)
 | 
			
		||||
    if resource ~= GetCurrentResourceName() then return end
 | 
			
		||||
    for _, playerId in ipairs(GetPlayers()) do
 | 
			
		||||
        local src = tonumber(playerId)
 | 
			
		||||
        local strSrc = tostring(src)
 | 
			
		||||
        if not Clothing.Players[strSrc] then
 | 
			
		||||
            Clothing.Players[strSrc] = Clothing.GetAppearance(src)
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
---Callback handler for retrieving a player's appearance data
 | 
			
		||||
Callback.Register('community_bridge:cb:GetAppearance', function(source)
 | 
			
		||||
    local src = source
 | 
			
		||||
    return Clothing.GetAppearance(src)
 | 
			
		||||
end)
 | 
			
		||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| 
						 | 
				
			
			@ -0,0 +1,8 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
if GetResourceState('fivem-appearance') == 'missing' then return end
 | 
			
		||||
if GetResourceState('rcore_clothing') ~= 'missing' then return end
 | 
			
		||||
Clothing = Clothing or {}
 | 
			
		||||
 | 
			
		||||
function Clothing.OpenMenu()
 | 
			
		||||
    TriggerEvent('qb-clothing:client:openMenu')
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,341 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
if GetResourceState('fivem-appearance') == 'missing' then return end
 | 
			
		||||
if GetResourceState('rcore_clothing') ~= 'missing' then return end
 | 
			
		||||
Clothing = Clothing or {}
 | 
			
		||||
Clothing.Players = {}
 | 
			
		||||
 | 
			
		||||
Callback = Callback or Require("lib/utility/shared/callbacks.lua")
 | 
			
		||||
Table = Table or Require('lib/utility/shared/tables.lua')
 | 
			
		||||
 | 
			
		||||
--- Internal function to get the full appearance data including skin, model, and converted format
 | 
			
		||||
---@param src number The server ID of the player
 | 
			
		||||
---@return table|nil The player's full appearance data or nil if not found
 | 
			
		||||
function Clothing.GetFullAppearanceData(src)
 | 
			
		||||
    src = src and tonumber(src)
 | 
			
		||||
    assert(src, "src is nil")
 | 
			
		||||
    local citId = Bridge.Framework.GetPlayerIdentifier(src)
 | 
			
		||||
    if not citId then return end
 | 
			
		||||
 | 
			
		||||
    if Clothing.Players[citId] then return Clothing.Players[citId] end
 | 
			
		||||
 | 
			
		||||
    local result = MySQL.query.await('SELECT * FROM playerskins WHERE citizenid = ? AND active = ?', { citId, 1 })
 | 
			
		||||
    if result[1] == nil then return end
 | 
			
		||||
 | 
			
		||||
    local model = result[1].model
 | 
			
		||||
    local skinData = json.decode(result[1].skin)
 | 
			
		||||
    local converted = skinData
 | 
			
		||||
 | 
			
		||||
    -- Store complete data in the cache
 | 
			
		||||
    Clothing.Players[citId] = {
 | 
			
		||||
        model = model,
 | 
			
		||||
        skin = skinData,
 | 
			
		||||
        converted = converted
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return Clothing.Players[citId]
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
--- Retrieves a player's converted appearance data for easy use across modules
 | 
			
		||||
---@param src number The server ID of the player
 | 
			
		||||
---@param fullData boolean Optional - If true, returns the full data object including skin and model
 | 
			
		||||
---@return table|nil The player's converted appearance data or full appearance data if fullData=true
 | 
			
		||||
function Clothing.GetAppearance(src, fullData)
 | 
			
		||||
    if fullData then
 | 
			
		||||
        return Clothing.GetFullAppearanceData(src)
 | 
			
		||||
    end
 | 
			
		||||
    local completeData = Clothing.GetFullAppearanceData(src)
 | 
			
		||||
    if not completeData then return nil end
 | 
			
		||||
    return completeData.converted
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
--- Sets a player's appearance based on the provided data
 | 
			
		||||
---@param src number The server ID of the player
 | 
			
		||||
---@param data table The appearance data to apply
 | 
			
		||||
---@param updateBackup boolean Whether to update the backup appearance data
 | 
			
		||||
---@return table|nil The updated player appearance data or nil if failed
 | 
			
		||||
function Clothing.SetAppearance(src, data, updateBackup, save)
 | 
			
		||||
    src = src and tonumber(src)
 | 
			
		||||
    assert(src, "src is nil")
 | 
			
		||||
    local citId = Bridge.Framework.GetPlayerIdentifier(src)
 | 
			
		||||
    if not citId then return end
 | 
			
		||||
    local model = GetEntityModel(GetPlayerPed(src))
 | 
			
		||||
    if not model then return end
 | 
			
		||||
    local converted = data
 | 
			
		||||
 | 
			
		||||
    -- Get full appearance data
 | 
			
		||||
    local currentClothing = Clothing.GetFullAppearanceData(src)
 | 
			
		||||
    if not currentClothing then return end
 | 
			
		||||
 | 
			
		||||
    local currentSkin = currentClothing.skin
 | 
			
		||||
    for k, v in pairs(converted) do
 | 
			
		||||
        currentSkin[k] = v
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    if not Clothing.Players[citId].backup or updateBackup then
 | 
			
		||||
        Clothing.Players[citId].backup = currentClothing.converted
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    Clothing.Players[citId] = Clothing.Players[citId] or {}
 | 
			
		||||
    Clothing.Players[citId].skin = currentSkin
 | 
			
		||||
    Clothing.Players[citId].model = model
 | 
			
		||||
    Clothing.Players[citId].converted = converted
 | 
			
		||||
    if save then
 | 
			
		||||
        MySQL.update.await('UPDATE playerskins SET skin = ? WHERE citizenid = ? AND active = ?', {
 | 
			
		||||
            json.encode(currentSkin),
 | 
			
		||||
            citId,
 | 
			
		||||
            1
 | 
			
		||||
        })
 | 
			
		||||
    end
 | 
			
		||||
    TriggerClientEvent('community_bridge:client:SetAppearance', src, Clothing.Players[citId].converted)
 | 
			
		||||
    return Clothing.Players[citId]
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
--- Sets a player's appearance based on gender-specific data
 | 
			
		||||
---@param src number The server ID of the player
 | 
			
		||||
---@param data table Table containing separate appearance data for male and female characters
 | 
			
		||||
---@return table|nil Appearance updated player appearance data or nil if failed
 | 
			
		||||
function Clothing.SetAppearanceExt(src, data)
 | 
			
		||||
    local tbl = Clothing.IsMale(src) and data.male or data.female
 | 
			
		||||
    Clothing.SetAppearance(src, tbl)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
--- Reverts a player's appearance to their backup appearance
 | 
			
		||||
---@param src number The server ID of the player
 | 
			
		||||
---@return boolean|nil Returns true if successful or nil if failed
 | 
			
		||||
function Clothing.Revert(src)
 | 
			
		||||
    src = src and tonumber(src)
 | 
			
		||||
    local currentClothing = Clothing.GetFullAppearanceData(src)
 | 
			
		||||
    if not currentClothing then return end
 | 
			
		||||
    local backup = currentClothing.backup
 | 
			
		||||
    if not backup then return end
 | 
			
		||||
    return Clothing.SetAppearance(src, backup)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function Clothing.OpenMenu(src)
 | 
			
		||||
    src = src and tonumber(src)
 | 
			
		||||
    assert(src, "src is nil")
 | 
			
		||||
    TriggerClientEvent('qb-clothing:client:openMenu', src) -- does this event  work while on esx?
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
--- Event handler for when a player loads into the server
 | 
			
		||||
--- Caches the player's appearance data
 | 
			
		||||
AddEventHandler('community_bridge:Server:OnPlayerLoaded', function(src)
 | 
			
		||||
    src = src and tonumber(src)
 | 
			
		||||
    assert(src, "src is nil")
 | 
			
		||||
    -- Use GetFullAppearanceData to cache the complete appearance
 | 
			
		||||
    Clothing.GetFullAppearanceData(src)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
--- Event handler for when a player disconnects from the server
 | 
			
		||||
--- Removes the player's appearance data from the cache
 | 
			
		||||
AddEventHandler('community_bridge:Server:OnPlayerUnload', function(src)
 | 
			
		||||
    src = src and tonumber(src)
 | 
			
		||||
    assert(src, "src is nil")
 | 
			
		||||
    local strSrc = tostring(src)
 | 
			
		||||
    Clothing.Players[strSrc] = nil
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
--- Event handler for when the resource starts
 | 
			
		||||
--- Caches appearance data for all currently connected players
 | 
			
		||||
AddEventHandler('onResourceStart', function(resource)
 | 
			
		||||
    if resource ~= GetCurrentResourceName() then return end
 | 
			
		||||
    for _, playerId in ipairs(GetPlayers()) do
 | 
			
		||||
        local src = tonumber(playerId)
 | 
			
		||||
        local strSrc = tostring(src)
 | 
			
		||||
        if not Clothing.Players[strSrc] then
 | 
			
		||||
            Clothing.Players[strSrc] = Clothing.GetAppearance(src)
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
--- Callback handler for retrieving a player's appearance data
 | 
			
		||||
Callback.Register('community_bridge:cb:GetAppearance', function(source)
 | 
			
		||||
    local src = source
 | 
			
		||||
    return Clothing.GetAppearance(src)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
RegisterCommand('clothing:debug', function(source, args, rawCommand)
 | 
			
		||||
    local src = source
 | 
			
		||||
    Clothing.SetAppearance(src, {
 | 
			
		||||
        components = {
 | 
			
		||||
            { component_id = 1, drawable = math.random(0, 50), texture = 0 },
 | 
			
		||||
            { component_id = 2, drawable = math.random(0, 50), texture = 0 },
 | 
			
		||||
            { component_id = 3, drawable = math.random(0, 50), texture = 0 },
 | 
			
		||||
            { component_id = 4, drawable = math.random(0, 50), texture = 0 },
 | 
			
		||||
            { component_id = 5, drawable = math.random(0, 50), texture = 0 },
 | 
			
		||||
            { component_id = 6, drawable = math.random(0, 50), texture = 0 },
 | 
			
		||||
            { component_id = 7, drawable = math.random(0, 50), texture = 0 },
 | 
			
		||||
            { component_id = 8, drawable = math.random(0, 50), texture = 0 },
 | 
			
		||||
        },
 | 
			
		||||
        props = {
 | 
			
		||||
            { prop_id = 3, drawable = 0, texture = 0 },
 | 
			
		||||
            { prop_id = 1, drawable = 0, texture = 0 },
 | 
			
		||||
            { prop_id = 2, drawable = 0, texture = 0 },
 | 
			
		||||
        }
 | 
			
		||||
    }, false, true)
 | 
			
		||||
end, false)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
RegisterCommand('clothing:revert', function(source, args, rawCommand)
 | 
			
		||||
    local src = source
 | 
			
		||||
    Clothing.Revert(src)
 | 
			
		||||
end, false)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
RegisterCommand('clothing:current', function(source, args, rawCommand)
 | 
			
		||||
    local src = source
 | 
			
		||||
    local currentClothing = Clothing.GetAppearance(src)
 | 
			
		||||
    if not currentClothing then return end
 | 
			
		||||
    print(json.encode(currentClothing, { indent = true }))
 | 
			
		||||
end, false)
 | 
			
		||||
 | 
			
		||||
RegisterCommand('clothing:openmenu', function(source, args, rawCommand)
 | 
			
		||||
    local src = source
 | 
			
		||||
    Clothing.OpenMenu(src)
 | 
			
		||||
end, false)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
-- This should be moved into unit tests
 | 
			
		||||
-- RegisterCommand('clothing:crowley', function(source, args, rawCommand)
 | 
			
		||||
--     local src = source
 | 
			
		||||
--     Clothing.SetAppearance(src, {
 | 
			
		||||
--         components= {
 | 
			
		||||
--             {
 | 
			
		||||
--                 drawable= 0,
 | 
			
		||||
--                 texture= 0,
 | 
			
		||||
--                 component_id= 0
 | 
			
		||||
--             },
 | 
			
		||||
--             {
 | 
			
		||||
--                 drawable= 0,
 | 
			
		||||
--                 texture= 0,
 | 
			
		||||
--                 component_id= 1
 | 
			
		||||
--             },
 | 
			
		||||
--             {
 | 
			
		||||
--                 drawable= 19,
 | 
			
		||||
--                 texture= 0,
 | 
			
		||||
--                 component_id= 2
 | 
			
		||||
--             },
 | 
			
		||||
--             {
 | 
			
		||||
--                 drawable= 6,
 | 
			
		||||
--                 texture= 0,
 | 
			
		||||
--                 component_id= 3
 | 
			
		||||
--             },
 | 
			
		||||
--             {
 | 
			
		||||
--                 drawable= 0,
 | 
			
		||||
--                 texture= 0,
 | 
			
		||||
--                 component_id= 4
 | 
			
		||||
--             },
 | 
			
		||||
--             {
 | 
			
		||||
--                 drawable= 0,
 | 
			
		||||
--                 texture= 0,
 | 
			
		||||
--                 component_id= 5
 | 
			
		||||
--             },
 | 
			
		||||
--             {
 | 
			
		||||
--                 drawable= 0,
 | 
			
		||||
--                 texture= 0,
 | 
			
		||||
--                 component_id= 6
 | 
			
		||||
--             },
 | 
			
		||||
--             {
 | 
			
		||||
--                 drawable= 0,
 | 
			
		||||
--                 texture= 0,
 | 
			
		||||
--                 component_id= 7
 | 
			
		||||
--             },
 | 
			
		||||
--             {
 | 
			
		||||
--                 drawable= 23,
 | 
			
		||||
--                 texture= 0,
 | 
			
		||||
--                 component_id= 8
 | 
			
		||||
--             },
 | 
			
		||||
--             {
 | 
			
		||||
--                 drawable= 0,
 | 
			
		||||
--                 texture= 0,
 | 
			
		||||
--                 component_id= 9
 | 
			
		||||
--             },
 | 
			
		||||
--             {
 | 
			
		||||
--                 drawable= 0,
 | 
			
		||||
--                 texture= 0,
 | 
			
		||||
--                 component_id= 10
 | 
			
		||||
--             },
 | 
			
		||||
--             {
 | 
			
		||||
--                 drawable= 4,
 | 
			
		||||
--                 texture= 2,
 | 
			
		||||
--                 component_id= 11
 | 
			
		||||
--             }
 | 
			
		||||
--         },
 | 
			
		||||
--         props= {
 | 
			
		||||
--             {
 | 
			
		||||
--                 drawable= 27,
 | 
			
		||||
--                 prop_id= 0,
 | 
			
		||||
--                 texture= 0
 | 
			
		||||
--             },
 | 
			
		||||
--             {
 | 
			
		||||
--                 drawable= -1,
 | 
			
		||||
--                 prop_id= 1,
 | 
			
		||||
--                 texture= -1
 | 
			
		||||
--             },
 | 
			
		||||
--             {
 | 
			
		||||
--                 drawable= -1,
 | 
			
		||||
--                 prop_id= 2,
 | 
			
		||||
--                 texture= -1
 | 
			
		||||
--             },
 | 
			
		||||
--             {
 | 
			
		||||
--                 drawable= -1,
 | 
			
		||||
--                 prop_id= 3,
 | 
			
		||||
--                 texture= -1
 | 
			
		||||
--             },
 | 
			
		||||
--             {
 | 
			
		||||
--                 drawable= -1,
 | 
			
		||||
--                 prop_id= 4,
 | 
			
		||||
--                 texture= -1
 | 
			
		||||
--             },
 | 
			
		||||
--             {
 | 
			
		||||
--                 drawable= -1,
 | 
			
		||||
--                 prop_id= 5,
 | 
			
		||||
--                 texture= -1
 | 
			
		||||
--             },
 | 
			
		||||
--             {
 | 
			
		||||
--                 drawable= -1,
 | 
			
		||||
--                 prop_id= 6,
 | 
			
		||||
--                 texture= -1
 | 
			
		||||
--             },
 | 
			
		||||
--             {
 | 
			
		||||
--                 drawable= -1,
 | 
			
		||||
--                 prop_id= 7,
 | 
			
		||||
--                 texture= -1
 | 
			
		||||
--             },
 | 
			
		||||
--             {
 | 
			
		||||
--                 drawable= -1,
 | 
			
		||||
--                 prop_id= 8,
 | 
			
		||||
--                 texture= -1
 | 
			
		||||
--             },
 | 
			
		||||
--             {
 | 
			
		||||
--                 drawable= -1,
 | 
			
		||||
--                 prop_id= 9,
 | 
			
		||||
--                 texture= -1
 | 
			
		||||
--             },
 | 
			
		||||
--             {
 | 
			
		||||
--                 drawable= -1,
 | 
			
		||||
--                 prop_id= 10,
 | 
			
		||||
--                 texture= -1
 | 
			
		||||
--             },
 | 
			
		||||
--             {
 | 
			
		||||
--                 drawable= -1,
 | 
			
		||||
--                 prop_id= 11,
 | 
			
		||||
--                 texture= -1
 | 
			
		||||
--             },
 | 
			
		||||
--             {
 | 
			
		||||
--                 drawable= -1,
 | 
			
		||||
--                 prop_id= 12,
 | 
			
		||||
--                 texture= -1
 | 
			
		||||
--             },
 | 
			
		||||
--             {
 | 
			
		||||
--                 drawable= -1,
 | 
			
		||||
--                 prop_id= 13,
 | 
			
		||||
--                 texture= -1
 | 
			
		||||
--             }
 | 
			
		||||
--         },
 | 
			
		||||
--         model= 1885233650
 | 
			
		||||
--     }, false, true)
 | 
			
		||||
-- end, false)
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,43 @@
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
-- {
 | 
			
		||||
--     male = {
 | 
			
		||||
--         name = "Short Sleeve",
 | 
			
		||||
--         outfitData = {
 | 
			
		||||
--             ["pants"] = {item = 133, texture = 0}, -- Pants
 | 
			
		||||
--             ["arms"] = {item = 31, texture = 0}, -- Arms
 | 
			
		||||
--             ["t-shirt"] = {item = 35, texture = 0}, -- T Shirt
 | 
			
		||||
--             ["vest"] = {item = 34, texture = 0}, -- Body Vest
 | 
			
		||||
--             ["torso2"] = {item = 48, texture = 0}, -- Jacket
 | 
			
		||||
--             ["shoes"] = {item = 52, texture = 0}, -- Shoes
 | 
			
		||||
--             ["accessory"] = {item = 0, texture = 0}, -- Neck Accessory
 | 
			
		||||
--             ["bag"] = {item = 0, texture = 0}, -- Bag
 | 
			
		||||
--             ["hat"] = {item = 0, texture = 0}, -- Hat
 | 
			
		||||
--             ["glass"] = {item = 0, texture = 0}, -- Glasses
 | 
			
		||||
--             ["mask"] = {item = 0, texture = 0} -- Mask
 | 
			
		||||
--         },
 | 
			
		||||
--         grades = {0, 1, 2, 3, 4},
 | 
			
		||||
--     },
 | 
			
		||||
--     female = {
 | 
			
		||||
--         name = "Short Sleeve",
 | 
			
		||||
--         outfitData = {
 | 
			
		||||
--             ["pants"] = {item = 133, texture = 0}, -- Pants
 | 
			
		||||
--             ["arms"] = {item = 31, texture = 0}, -- Arms
 | 
			
		||||
--             ["t-shirt"] = {item = 35, texture = 0}, -- T Shirt
 | 
			
		||||
--             ["vest"] = {item = 34, texture = 0}, -- Body Vest
 | 
			
		||||
--             ["torso2"] = {item = 48, texture = 0}, -- Jacket
 | 
			
		||||
--             ["shoes"] = {item = 52, texture = 0}, -- Shoes
 | 
			
		||||
--             ["accessory"] = {item = 0, texture = 0}, -- Neck Accessory
 | 
			
		||||
--             ["bag"] = {item = 0, texture = 0}, -- Bag
 | 
			
		||||
--             ["hat"] = {item = 0, texture = 0}, -- Hat
 | 
			
		||||
--             ["glass"] = {item = 0, texture = 0}, -- Glasses
 | 
			
		||||
--             ["mask"] = {item = 0, texture = 0} -- Mask
 | 
			
		||||
--         },
 | 
			
		||||
--     }
 | 
			
		||||
-- }
 | 
			
		||||
 | 
			
		||||
-- function Clothing.ConvertData(data)
 | 
			
		||||
--     return data 
 | 
			
		||||
-- end
 | 
			
		||||
 | 
			
		||||
-- This still needed?
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,8 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
if GetResourceState('illenium-appearance') == 'missing' then return end
 | 
			
		||||
if GetResourceState('rcore_clothing') ~= 'missing' then return end
 | 
			
		||||
Clothing = Clothing or {}
 | 
			
		||||
 | 
			
		||||
function Clothing.OpenMenu()
 | 
			
		||||
    TriggerEvent('qb-clothing:client:openMenu')
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,253 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
if GetResourceState('illenium-appearance') == 'missing' then return end
 | 
			
		||||
if GetResourceState('rcore_clothing') ~= 'missing' then return end
 | 
			
		||||
Clothing = Clothing or {}
 | 
			
		||||
Clothing.Players = {}
 | 
			
		||||
 | 
			
		||||
Callback = Callback or Require("lib/utility/shared/callbacks.lua")
 | 
			
		||||
Table = Table or Require('lib/utility/shared/tables.lua')
 | 
			
		||||
 | 
			
		||||
--- Internal function to get the full appearance data including skin, model, and converted format
 | 
			
		||||
---@param src number The server ID of the player
 | 
			
		||||
---@return table|nil The player's full appearance data or nil if not found
 | 
			
		||||
function Clothing.GetFullAppearanceData(src)
 | 
			
		||||
    src = src and tonumber(src)
 | 
			
		||||
    assert(src, "src is nil")
 | 
			
		||||
    local citId = Bridge.Framework.GetPlayerIdentifier(src)
 | 
			
		||||
    if not citId then return end
 | 
			
		||||
 | 
			
		||||
    if Clothing.Players[citId] then return Clothing.Players[citId] end
 | 
			
		||||
 | 
			
		||||
    local result = MySQL.query.await('SELECT * FROM playerskins WHERE citizenid = ? AND active = ?', { citId, 1 })
 | 
			
		||||
    if result[1] == nil then return end
 | 
			
		||||
 | 
			
		||||
    local model = result[1].model
 | 
			
		||||
    local skinData = json.decode(result[1].skin)
 | 
			
		||||
    local converted = skinData
 | 
			
		||||
 | 
			
		||||
    -- Store complete data in the cache
 | 
			
		||||
    Clothing.Players[citId] = {
 | 
			
		||||
        model = model,
 | 
			
		||||
        skin = skinData,
 | 
			
		||||
        converted = converted
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return Clothing.Players[citId]
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
--- Retrieves a player's converted appearance data for easy use across modules
 | 
			
		||||
---@param src number The server ID of the player
 | 
			
		||||
---@param fullData boolean Optional - If true, returns the full data object including skin and model
 | 
			
		||||
---@return table|nil The player's converted appearance data or full appearance data if fullData=true
 | 
			
		||||
function Clothing.GetAppearance(src, fullData)
 | 
			
		||||
    if fullData then
 | 
			
		||||
        return Clothing.GetFullAppearanceData(src)
 | 
			
		||||
    end
 | 
			
		||||
    local completeData = Clothing.GetFullAppearanceData(src)
 | 
			
		||||
    if not completeData then return nil end
 | 
			
		||||
    return completeData.converted
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
--- Sets a player's appearance based on the provided data
 | 
			
		||||
---@param src number The server ID of the player
 | 
			
		||||
---@param data table The appearance data to apply
 | 
			
		||||
---@param updateBackup boolean Whether to update the backup appearance data
 | 
			
		||||
---@return table|nil The updated player appearance data or nil if failed
 | 
			
		||||
function Clothing.SetAppearance(src, data, updateBackup, save)
 | 
			
		||||
    src = src and tonumber(src)
 | 
			
		||||
    assert(src, "src is nil")
 | 
			
		||||
    local citId = Bridge.Framework.GetPlayerIdentifier(src)
 | 
			
		||||
    if not citId then return end
 | 
			
		||||
    local model = GetEntityModel(GetPlayerPed(src))
 | 
			
		||||
    if not model then return end
 | 
			
		||||
    local converted = data
 | 
			
		||||
 | 
			
		||||
    -- Get full appearance data
 | 
			
		||||
    local currentClothing = Clothing.GetFullAppearanceData(src)
 | 
			
		||||
    if not currentClothing then return end
 | 
			
		||||
 | 
			
		||||
    local currentSkin = currentClothing.skin
 | 
			
		||||
    for k, v in pairs(converted) do
 | 
			
		||||
        currentSkin[k] = v
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    if not Clothing.Players[citId].backup or updateBackup then
 | 
			
		||||
        Clothing.Players[citId].backup = currentClothing.converted
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    Clothing.Players[citId] = Clothing.Players[citId] or {}
 | 
			
		||||
    Clothing.Players[citId].skin = currentSkin
 | 
			
		||||
    Clothing.Players[citId].model = model
 | 
			
		||||
    Clothing.Players[citId].converted = converted
 | 
			
		||||
    if save then
 | 
			
		||||
        MySQL.update.await('UPDATE playerskins SET skin = ? WHERE citizenid = ? AND active = ?', {
 | 
			
		||||
            json.encode(currentSkin),
 | 
			
		||||
            citId,
 | 
			
		||||
            1
 | 
			
		||||
        })
 | 
			
		||||
    end
 | 
			
		||||
    TriggerClientEvent('community_bridge:client:SetAppearance', src, Clothing.Players[citId].converted)
 | 
			
		||||
    return Clothing.Players[citId]
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
--- Sets a player's appearance based on gender-specific data
 | 
			
		||||
---@param src number The server ID of the player
 | 
			
		||||
---@param data table Table containing separate appearance data for male and female characters
 | 
			
		||||
---@return table|nil Appearance updated player appearance data or nil if failed
 | 
			
		||||
function Clothing.SetAppearanceExt(src, data)
 | 
			
		||||
    local tbl = Clothing.IsMale(src) and data.male or data.female
 | 
			
		||||
    Clothing.SetAppearance(src, tbl)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
--- Reverts a player's appearance to their backup appearance
 | 
			
		||||
---@param src number The server ID of the player
 | 
			
		||||
---@return boolean|nil Returns true if successful or nil if failed
 | 
			
		||||
function Clothing.Revert(src)
 | 
			
		||||
    src = src and tonumber(src)
 | 
			
		||||
    assert(src, "src is nil")
 | 
			
		||||
    local currentClothing = Clothing.GetFullAppearanceData(src)
 | 
			
		||||
    if not currentClothing then return end
 | 
			
		||||
    local backup = currentClothing.backup
 | 
			
		||||
    print(src, backup)
 | 
			
		||||
    if not backup then return end
 | 
			
		||||
    return Clothing.SetAppearance(src, backup)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function Clothing.OpenMenu(src)
 | 
			
		||||
    src = src and tonumber(src)
 | 
			
		||||
    assert(src, "src is nil")
 | 
			
		||||
    TriggerClientEvent('qb-clothing:client:openMenu', src)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
--- Event handler for when a player loads into the server
 | 
			
		||||
--- Caches the player's appearance data
 | 
			
		||||
AddEventHandler('community_bridge:Server:OnPlayerLoaded', function(src)
 | 
			
		||||
    src = src and tonumber(src)
 | 
			
		||||
    assert(src, "src is nil")
 | 
			
		||||
    -- Use GetFullAppearanceData to cache the complete appearance
 | 
			
		||||
    Clothing.GetFullAppearanceData(src)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
--- Event handler for when a player disconnects from the server
 | 
			
		||||
--- Removes the player's appearance data from the cache
 | 
			
		||||
AddEventHandler('community_bridge:Server:OnPlayerUnload', function(src)
 | 
			
		||||
    src = src and tonumber(src)
 | 
			
		||||
    assert(src, "src is nil")
 | 
			
		||||
    local strSrc = tostring(src)
 | 
			
		||||
    Clothing.Players[strSrc] = nil
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
--- Event handler for when the resource starts
 | 
			
		||||
--- Caches appearance data for all currently connected players
 | 
			
		||||
AddEventHandler('onResourceStart', function(resource)
 | 
			
		||||
    if resource ~= GetCurrentResourceName() then return end
 | 
			
		||||
    for _, playerId in ipairs(GetPlayers()) do
 | 
			
		||||
        local src = tonumber(playerId)
 | 
			
		||||
        local strSrc = tostring(src)
 | 
			
		||||
        if not Clothing.Players[strSrc] then
 | 
			
		||||
            Clothing.Players[strSrc] = Clothing.GetAppearance(src)
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
--- Callback handler for retrieving a player's appearance data
 | 
			
		||||
Callback.Register('community_bridge:cb:GetAppearance', function(source)
 | 
			
		||||
    local src = source
 | 
			
		||||
    return Clothing.GetAppearance(src)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
-- The below Should go to unit test
 | 
			
		||||
RegisterCommand('clothing:debug', function(source, args, rawCommand)
 | 
			
		||||
    local src = source
 | 
			
		||||
    Clothing.SetAppearance(src, {
 | 
			
		||||
        components = {
 | 
			
		||||
            { component_id = 0,  drawable = math.random(0, 50), texture = 0 },
 | 
			
		||||
            { component_id = 1,  drawable = math.random(0, 50), texture = 0 },
 | 
			
		||||
            { component_id = 2,  drawable = math.random(0, 50), texture = 0 },
 | 
			
		||||
            { component_id = 3,  drawable = math.random(0, 50), texture = 0 },
 | 
			
		||||
            { component_id = 4,  drawable = math.random(0, 50), texture = 0 },
 | 
			
		||||
            { component_id = 5,  drawable = math.random(0, 50), texture = 0 },
 | 
			
		||||
            { component_id = 6,  drawable = math.random(0, 50), texture = 0 },
 | 
			
		||||
            { component_id = 7,  drawable = math.random(0, 50), texture = 0 },
 | 
			
		||||
            { component_id = 8,  drawable = math.random(0, 50), texture = 0 },
 | 
			
		||||
            { component_id = 9,  drawable = math.random(0, 50), texture = 0 },
 | 
			
		||||
            { component_id = 10, drawable = math.random(0, 50), texture = 0 },
 | 
			
		||||
            { component_id = 11, drawable = math.random(0, 50), texture = 0 },
 | 
			
		||||
        },
 | 
			
		||||
        props = {
 | 
			
		||||
            { prop_id = 0,  drawable = math.random(0, 50), texture = 0 },
 | 
			
		||||
            { prop_id = 1,  drawable = math.random(0, 50), texture = 0 },
 | 
			
		||||
            { prop_id = 2,  drawable = math.random(0, 50), texture = 0 },
 | 
			
		||||
            { prop_id = 3,  drawable = math.random(0, 50), texture = 0 },
 | 
			
		||||
            { prop_id = 4,  drawable = math.random(0, 50), texture = 0 },
 | 
			
		||||
            { prop_id = 5,  drawable = math.random(0, 50), texture = 0 },
 | 
			
		||||
            { prop_id = 6,  drawable = math.random(0, 50), texture = 0 },
 | 
			
		||||
            { prop_id = 7,  drawable = math.random(0, 50), texture = 0 },
 | 
			
		||||
            { prop_id = 8,  drawable = math.random(0, 50), texture = 0 },
 | 
			
		||||
            { prop_id = 9,  drawable = math.random(0, 50), texture = 0 },
 | 
			
		||||
            { prop_id = 10, drawable = math.random(0, 50), texture = 0 },
 | 
			
		||||
            { prop_id = 11, drawable = math.random(0, 50), texture = 0 },
 | 
			
		||||
            { prop_id = 12, drawable = math.random(0, 50), texture = 0 },
 | 
			
		||||
            { prop_id = 13, drawable = math.random(0, 50), texture = 0 },
 | 
			
		||||
        }
 | 
			
		||||
    }, false, true)
 | 
			
		||||
end, false)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
RegisterCommand('clothing:revert', function(source, args, rawCommand)
 | 
			
		||||
    local src = source
 | 
			
		||||
    Clothing.Revert(src)
 | 
			
		||||
end, false)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
RegisterCommand('clothing:current', function(source, args, rawCommand)
 | 
			
		||||
    local src = source
 | 
			
		||||
    local currentClothing = Clothing.GetAppearance(src)
 | 
			
		||||
    if not currentClothing then return end
 | 
			
		||||
    print(json.encode(currentClothing, { indent = true }))
 | 
			
		||||
end, false)
 | 
			
		||||
 | 
			
		||||
RegisterCommand('clothing:openmenu', function(source, args, rawCommand)
 | 
			
		||||
    local src = source
 | 
			
		||||
    Clothing.OpenMenu(src)
 | 
			
		||||
end, false)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
RegisterCommand('clothing:crowley', function(source, args, rawCommand)
 | 
			
		||||
    local src = source
 | 
			
		||||
    Clothing.SetAppearance(src, {
 | 
			
		||||
        components = {
 | 
			
		||||
            { drawable = 0,  texture = 0, component_id = 0 },
 | 
			
		||||
            { drawable = 0,  texture = 0, component_id = 1 },
 | 
			
		||||
            { drawable = 19, texture = 0, component_id = 2 },
 | 
			
		||||
            { drawable = 6,  texture = 0, component_id = 3 },
 | 
			
		||||
            { drawable = 0,  texture = 0, component_id = 4 },
 | 
			
		||||
            { drawable = 0,  texture = 0, component_id = 5 },
 | 
			
		||||
            { drawable = 0,  texture = 0, component_id = 6 },
 | 
			
		||||
            { drawable = 0,  texture = 0, component_id = 7 },
 | 
			
		||||
            { drawable = 23, texture = 0, component_id = 8 },
 | 
			
		||||
            { drawable = 0,  texture = 0, component_id = 9 },
 | 
			
		||||
            { drawable = 0,  texture = 0, component_id = 10 },
 | 
			
		||||
            { drawable = 4,  texture = 2, component_id = 11 }
 | 
			
		||||
        },
 | 
			
		||||
        props = {
 | 
			
		||||
            { drawable = 27, prop_id = 0,  texture = 0 },
 | 
			
		||||
            { drawable = 0,  prop_id = 1,  texture = 0 },
 | 
			
		||||
            { drawable = 0,  prop_id = 2,  texture = 0 },
 | 
			
		||||
            { drawable = 0,  prop_id = 3,  texture = 0 },
 | 
			
		||||
            { drawable = 0,  prop_id = 4,  texture = 0 },
 | 
			
		||||
            { drawable = 0,  prop_id = 5,  texture = 0 },
 | 
			
		||||
            { drawable = 0,  prop_id = 6,  texture = 0 },
 | 
			
		||||
            { drawable = 0,  prop_id = 7,  texture = 0 },
 | 
			
		||||
            { drawable = 0,  prop_id = 8,  texture = 0 },
 | 
			
		||||
            { drawable = 0,  prop_id = 9,  texture = 0 },
 | 
			
		||||
            { drawable = 0,  prop_id = 10, texture = 0 },
 | 
			
		||||
            { drawable = 0,  prop_id = 11, texture = 0 },
 | 
			
		||||
            { drawable = 0,  prop_id = 12, texture = 0 },
 | 
			
		||||
            { drawable = 0,  prop_id = 13, texture = 0 }
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
    }, false, true)
 | 
			
		||||
end, false)
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,222 @@
 | 
			
		|||
-- Get appearence data
 | 
			
		||||
 | 
			
		||||
-- {
 | 
			
		||||
--     "tattoos": {
 | 
			
		||||
--         "ZONE_HAIR": [
 | 
			
		||||
--             {
 | 
			
		||||
--                 "label": "hair-0-188",
 | 
			
		||||
--                 "collection": "multiplayer_overlays",
 | 
			
		||||
--                 "name": "hair-0-188",
 | 
			
		||||
--                 "hashFemale": "FM_F_Hair_003_c",
 | 
			
		||||
--                 "hashMale": "FM_M_Hair_003_c",
 | 
			
		||||
--                 "zone": "ZONE_HAIR"
 | 
			
		||||
--             }
 | 
			
		||||
--         ]
 | 
			
		||||
--     },
 | 
			
		||||
--     "components": [
 | 
			
		||||
--         {
 | 
			
		||||
--             "texture": -1,
 | 
			
		||||
--             "drawable": -1,
 | 
			
		||||
--             "component_id": 0
 | 
			
		||||
--         },
 | 
			
		||||
--         {
 | 
			
		||||
--             "texture": -1,
 | 
			
		||||
--             "drawable": -1,
 | 
			
		||||
--             "component_id": 1
 | 
			
		||||
--         },
 | 
			
		||||
--         {
 | 
			
		||||
--             "texture": -1,
 | 
			
		||||
--             "drawable": -1,
 | 
			
		||||
--             "component_id": 2
 | 
			
		||||
--         },
 | 
			
		||||
--         {
 | 
			
		||||
--             "texture": -1,
 | 
			
		||||
--             "drawable": -1,
 | 
			
		||||
--             "component_id": 3
 | 
			
		||||
--         },
 | 
			
		||||
--         {
 | 
			
		||||
--             "texture": -1,
 | 
			
		||||
--             "drawable": -1,
 | 
			
		||||
--             "component_id": 4
 | 
			
		||||
--         },
 | 
			
		||||
--         {
 | 
			
		||||
--             "texture": -1,
 | 
			
		||||
--             "drawable": -1,
 | 
			
		||||
--             "component_id": 5
 | 
			
		||||
--         },
 | 
			
		||||
--         {
 | 
			
		||||
--             "texture": -1,
 | 
			
		||||
--             "drawable": -1,
 | 
			
		||||
--             "component_id": 6
 | 
			
		||||
--         },
 | 
			
		||||
--         {
 | 
			
		||||
--             "texture": -1,
 | 
			
		||||
--             "drawable": -1,
 | 
			
		||||
--             "component_id": 7
 | 
			
		||||
--         },
 | 
			
		||||
--         {
 | 
			
		||||
--             "texture": -1,
 | 
			
		||||
--             "drawable": -1,
 | 
			
		||||
--             "component_id": 8
 | 
			
		||||
--         },
 | 
			
		||||
--         {
 | 
			
		||||
--             "texture": -1,
 | 
			
		||||
--             "drawable": -1,
 | 
			
		||||
--             "component_id": 9
 | 
			
		||||
--         },
 | 
			
		||||
--         {
 | 
			
		||||
--             "texture": -1,
 | 
			
		||||
--             "drawable": -1,
 | 
			
		||||
--             "component_id": 10
 | 
			
		||||
--         },
 | 
			
		||||
--         {
 | 
			
		||||
--             "texture": -1,
 | 
			
		||||
--             "drawable": -1,
 | 
			
		||||
--             "component_id": 11
 | 
			
		||||
--         }
 | 
			
		||||
--     ],
 | 
			
		||||
--     "headBlend": {
 | 
			
		||||
--         "skinSecond": 0,
 | 
			
		||||
--         "skinMix": 0.0,
 | 
			
		||||
--         "shapeFirst": 0,
 | 
			
		||||
--         "shapeThird": 0,
 | 
			
		||||
--         "skinFirst": 0,
 | 
			
		||||
--         "shapeMix": 0.0,
 | 
			
		||||
--         "shapeSecond": 0,
 | 
			
		||||
--         "skinThird": 0,
 | 
			
		||||
--         "thirdMix": 0.0
 | 
			
		||||
--     },
 | 
			
		||||
--     "hair": {
 | 
			
		||||
--         "texture": -1,
 | 
			
		||||
--         "style": -1,
 | 
			
		||||
--         "color": -1,
 | 
			
		||||
--         "highlight": -1
 | 
			
		||||
--     },
 | 
			
		||||
--     "eyeColor": -1,
 | 
			
		||||
--     "headOverlays": {
 | 
			
		||||
--         "lipstick": {
 | 
			
		||||
--             "color": 0,
 | 
			
		||||
--             "style": 0,
 | 
			
		||||
--             "opacity": 0.0,
 | 
			
		||||
--             "secondColor": 0
 | 
			
		||||
--         },
 | 
			
		||||
--         "moleAndFreckles": {
 | 
			
		||||
--             "color": 0,
 | 
			
		||||
--             "style": 0,
 | 
			
		||||
--             "opacity": 0.0,
 | 
			
		||||
--             "secondColor": 0
 | 
			
		||||
--         },
 | 
			
		||||
--         "ageing": {
 | 
			
		||||
--             "color": 0,
 | 
			
		||||
--             "style": 0,
 | 
			
		||||
--             "opacity": 0.0,
 | 
			
		||||
--             "secondColor": 0
 | 
			
		||||
--         },
 | 
			
		||||
--         "makeUp": {
 | 
			
		||||
--             "color": 0,
 | 
			
		||||
--             "style": 0,
 | 
			
		||||
--             "opacity": 0.0,
 | 
			
		||||
--             "secondColor": 0
 | 
			
		||||
--         },
 | 
			
		||||
--         "beard": {
 | 
			
		||||
--             "color": 0,
 | 
			
		||||
--             "style": 0,
 | 
			
		||||
--             "opacity": 0.0,
 | 
			
		||||
--             "secondColor": 0
 | 
			
		||||
--         },
 | 
			
		||||
--         "blush": {
 | 
			
		||||
--             "color": 0,
 | 
			
		||||
--             "style": 0,
 | 
			
		||||
--             "opacity": 0.0,
 | 
			
		||||
--             "secondColor": 0
 | 
			
		||||
--         },
 | 
			
		||||
--         "complexion": {
 | 
			
		||||
--             "color": 0,
 | 
			
		||||
--             "style": 0,
 | 
			
		||||
--             "opacity": 0.0,
 | 
			
		||||
--             "secondColor": 0
 | 
			
		||||
--         },
 | 
			
		||||
--         "bodyBlemishes": {
 | 
			
		||||
--             "color": 0,
 | 
			
		||||
--             "style": 0,
 | 
			
		||||
--             "opacity": 0.0,
 | 
			
		||||
--             "secondColor": 0
 | 
			
		||||
--         },
 | 
			
		||||
--         "eyebrows": {
 | 
			
		||||
--             "color": 0,
 | 
			
		||||
--             "style": 0,
 | 
			
		||||
--             "opacity": 0.0,
 | 
			
		||||
--             "secondColor": 0
 | 
			
		||||
--         },
 | 
			
		||||
--         "chestHair": {
 | 
			
		||||
--             "color": 0,
 | 
			
		||||
--             "style": 0,
 | 
			
		||||
--             "opacity": 0.0,
 | 
			
		||||
--             "secondColor": 0
 | 
			
		||||
--         },
 | 
			
		||||
--         "sunDamage": {
 | 
			
		||||
--             "color": 0,
 | 
			
		||||
--             "style": 0,
 | 
			
		||||
--             "opacity": 0.0,
 | 
			
		||||
--             "secondColor": 0
 | 
			
		||||
--         },
 | 
			
		||||
--         "blemishes": {
 | 
			
		||||
--             "color": 0,
 | 
			
		||||
--             "style": 0,
 | 
			
		||||
--             "opacity": 0.0,
 | 
			
		||||
--             "secondColor": 0
 | 
			
		||||
--         }
 | 
			
		||||
--     },
 | 
			
		||||
--     "faceFeatures": {
 | 
			
		||||
--         "jawBoneBackSize": 0.0,
 | 
			
		||||
--         "noseWidth": 0.0,
 | 
			
		||||
--         "eyeBrownHigh": 0.0,
 | 
			
		||||
--         "chinBoneSize": 0.0,
 | 
			
		||||
--         "chinHole": 0.0,
 | 
			
		||||
--         "neckThickness": 0.0,
 | 
			
		||||
--         "noseBoneTwist": 0.0,
 | 
			
		||||
--         "noseBoneHigh": 0.0,
 | 
			
		||||
--         "nosePeakHigh": 0.0,
 | 
			
		||||
--         "nosePeakSize": 0.0,
 | 
			
		||||
--         "eyesOpening": 0.0,
 | 
			
		||||
--         "cheeksBoneHigh": 0.0,
 | 
			
		||||
--         "cheeksBoneWidth": 0.0,
 | 
			
		||||
--         "cheeksWidth": 0.0,
 | 
			
		||||
--         "lipsThickness": 0.0,
 | 
			
		||||
--         "nosePeakLowering": 0.0,
 | 
			
		||||
--         "jawBoneWidth": 0.0,
 | 
			
		||||
--         "eyeBrownForward": 0.0,
 | 
			
		||||
--         "chinBoneLenght": 0.0,
 | 
			
		||||
--         "chinBoneLowering": 0.0
 | 
			
		||||
--     },
 | 
			
		||||
--     "model": "mp_m_freemode_01",
 | 
			
		||||
--     "props": [
 | 
			
		||||
--         {
 | 
			
		||||
--             "drawable": -1,
 | 
			
		||||
--             "prop_id": 0,
 | 
			
		||||
--             "texture": -1
 | 
			
		||||
--         },
 | 
			
		||||
--         {
 | 
			
		||||
--             "drawable": -1,
 | 
			
		||||
--             "prop_id": 1,
 | 
			
		||||
--             "texture": -1
 | 
			
		||||
--         },
 | 
			
		||||
--         {
 | 
			
		||||
--             "drawable": -1,
 | 
			
		||||
--             "prop_id": 2,
 | 
			
		||||
--             "texture": -1
 | 
			
		||||
--         },
 | 
			
		||||
--         {
 | 
			
		||||
--             "drawable": -1,
 | 
			
		||||
--             "prop_id": 6,
 | 
			
		||||
--             "texture": -1
 | 
			
		||||
--         },
 | 
			
		||||
--         {
 | 
			
		||||
--             "drawable": -1,
 | 
			
		||||
--             "prop_id": 7,
 | 
			
		||||
--             "texture": -1
 | 
			
		||||
--         }
 | 
			
		||||
--     ]
 | 
			
		||||
-- }
 | 
			
		||||
 | 
			
		||||
-- this still needed?
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,8 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
if GetResourceState('qb-clothing') == 'missing' then return end
 | 
			
		||||
if GetResourceState('rcore_clothing') ~= 'missing' then return end
 | 
			
		||||
Clothing = Clothing or {}
 | 
			
		||||
 | 
			
		||||
function Clothing.OpenMenu()
 | 
			
		||||
    TriggerEvent('qb-clothing:client:openMenu')
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,239 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
if GetResourceState('qb-clothing') == 'missing' then return end
 | 
			
		||||
if GetResourceState('rcore_clothing') ~= 'missing' then return end
 | 
			
		||||
Clothing = Clothing or {}
 | 
			
		||||
Clothing.Players = {}
 | 
			
		||||
 | 
			
		||||
Callback = Callback or Require("lib/utility/shared/callbacks.lua")
 | 
			
		||||
Table = Table or Require('lib/utility/shared/tables.lua')
 | 
			
		||||
QBCore = QBCore or exports['qb-core']:GetCoreObject() -- probably easiest for now to call the Framework module
 | 
			
		||||
 | 
			
		||||
--- Internal function to get the full appearance data including skin, model, and converted format
 | 
			
		||||
---@param src number The server ID of the player
 | 
			
		||||
---@return table|nil The player's full appearance data or nil if not found
 | 
			
		||||
function Clothing.GetFullAppearanceData(src)
 | 
			
		||||
    src = src and tonumber(src)
 | 
			
		||||
    assert(src, "src is nil")
 | 
			
		||||
    local Player = QBCore.Functions.GetPlayer(src)
 | 
			
		||||
    if not Player then return end
 | 
			
		||||
    local citId = Player.PlayerData.citizenid
 | 
			
		||||
    if not citId then return end
 | 
			
		||||
 | 
			
		||||
    if Clothing.Players[citId] then return Clothing.Players[citId] end
 | 
			
		||||
 | 
			
		||||
    local result = MySQL.query.await('SELECT * FROM playerskins WHERE citizenid = ? AND active = ?', { citId, 1 })
 | 
			
		||||
    if result[1] == nil then return end
 | 
			
		||||
 | 
			
		||||
    local model = Player.PlayerData.model
 | 
			
		||||
    local skinData = json.decode(result[1].skin)
 | 
			
		||||
    local converted = Clothing.ConvertToDefault(skinData)
 | 
			
		||||
 | 
			
		||||
    -- Store complete data in the cache
 | 
			
		||||
    Clothing.Players[citId] = {
 | 
			
		||||
        model = model,
 | 
			
		||||
        skin = skinData,
 | 
			
		||||
        converted = converted
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return Clothing.Players[citId]
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
--- Retrieves a player's converted appearance data for easy use across modules
 | 
			
		||||
---@param src number The server ID of the player
 | 
			
		||||
---@param fullData boolean Optional - If true, returns the full data object including skin and model
 | 
			
		||||
---@return table|nil The player's converted appearance data or full appearance data if fullData=true
 | 
			
		||||
function Clothing.GetAppearance(src, fullData)
 | 
			
		||||
    if fullData then
 | 
			
		||||
        return Clothing.GetFullAppearanceData(src)
 | 
			
		||||
    end
 | 
			
		||||
    local completeData = Clothing.GetFullAppearanceData(src)
 | 
			
		||||
    if not completeData then return nil end
 | 
			
		||||
    return completeData.converted
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
--- Sets a player's appearance based on the provided data
 | 
			
		||||
---@param src number The server ID of the player
 | 
			
		||||
---@param data table The appearance data to apply
 | 
			
		||||
---@param updateBackup boolean Whether to update the backup appearance data
 | 
			
		||||
---@return table|nil The updated player appearance data or nil if failed
 | 
			
		||||
function Clothing.SetAppearance(src, data, updateBackup, save)
 | 
			
		||||
    src = src and tonumber(src)
 | 
			
		||||
    assert(src, "src is nil")
 | 
			
		||||
    local Player = QBCore.Functions.GetPlayer(src)
 | 
			
		||||
    if not Player then return end
 | 
			
		||||
    local citId = Player.PlayerData.citizenid
 | 
			
		||||
    if not citId then return end
 | 
			
		||||
    local model = GetEntityModel(GetPlayerPed(src))
 | 
			
		||||
    if not model then return end
 | 
			
		||||
    local converted = Clothing.ConvertFromDefault(data)
 | 
			
		||||
 | 
			
		||||
    -- Get full appearance data
 | 
			
		||||
    local currentClothing = Clothing.GetFullAppearanceData(src)
 | 
			
		||||
    if not currentClothing then return end
 | 
			
		||||
 | 
			
		||||
    local currentSkin = currentClothing.skin
 | 
			
		||||
    for k, v in pairs(converted) do
 | 
			
		||||
        currentSkin[k] = v
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    if not Clothing.Players[citId].backup or updateBackup then
 | 
			
		||||
        Clothing.Players[citId].backup = currentClothing.converted
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    Clothing.Players[citId] = Clothing.Players[citId] or {}
 | 
			
		||||
    Clothing.Players[citId].skin = currentSkin
 | 
			
		||||
    Clothing.Players[citId].model = model
 | 
			
		||||
    Clothing.Players[citId].converted = Clothing.ConvertToDefault(currentSkin)
 | 
			
		||||
    if save then
 | 
			
		||||
        MySQL.update.await('UPDATE playerskins SET skin = ? WHERE citizenid = ? AND active = ?', {
 | 
			
		||||
            json.encode(currentSkin),
 | 
			
		||||
            citId,
 | 
			
		||||
            1
 | 
			
		||||
        })
 | 
			
		||||
    end
 | 
			
		||||
    TriggerClientEvent('community_bridge:client:SetAppearance', src, Clothing.Players[citId].converted)
 | 
			
		||||
    return Clothing.Players[citId]
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
--- Sets a player's appearance based on gender-specific data
 | 
			
		||||
---@param src number The server ID of the player
 | 
			
		||||
---@param data table Table containing separate appearance data for male and female characters
 | 
			
		||||
---@return table|nil Appearance updated player appearance data or nil if failed
 | 
			
		||||
function Clothing.SetAppearanceExt(src, data)
 | 
			
		||||
    local tbl = Clothing.IsMale(src) and data.male or data.female
 | 
			
		||||
    Clothing.SetAppearance(src, tbl)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
--- Reverts a player's appearance to their backup appearance
 | 
			
		||||
---@param src number The server ID of the player
 | 
			
		||||
---@return boolean|nil Returns true if successful or nil if failed
 | 
			
		||||
function Clothing.Revert(src)
 | 
			
		||||
    src = src and tonumber(src)
 | 
			
		||||
    assert(src, "src is nil")
 | 
			
		||||
    local currentClothing = Clothing.GetFullAppearanceData(src)
 | 
			
		||||
    if not currentClothing then return end
 | 
			
		||||
    local backup = currentClothing.backup
 | 
			
		||||
    print(src, backup)
 | 
			
		||||
    if not backup then return end
 | 
			
		||||
    return Clothing.SetAppearance(src, backup)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function Clothing.OpenMenu(src)
 | 
			
		||||
    src = src and tonumber(src)
 | 
			
		||||
    assert(src, "src is nil")
 | 
			
		||||
    TriggerClientEvent('qb-clothing:client:openMenu', src)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
--- Event handler for when a player loads into the server
 | 
			
		||||
--- Caches the player's appearance data
 | 
			
		||||
AddEventHandler('community_bridge:Server:OnPlayerLoaded', function(src)
 | 
			
		||||
    src = src and tonumber(src)
 | 
			
		||||
    assert(src, "src is nil")
 | 
			
		||||
    local Player = QBCore.Functions.GetPlayer(src)
 | 
			
		||||
    if not Player then return end
 | 
			
		||||
    local citId = Player.PlayerData.citizenid
 | 
			
		||||
    if not citId then return end
 | 
			
		||||
 | 
			
		||||
    -- Use GetFullAppearanceData to cache the complete appearance
 | 
			
		||||
    Clothing.GetFullAppearanceData(src)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
--- Event handler for when a player disconnects from the server
 | 
			
		||||
--- Removes the player's appearance data from the cache
 | 
			
		||||
AddEventHandler('community_bridge:Server:OnPlayerUnload', function(src)
 | 
			
		||||
    src = src and tonumber(src)
 | 
			
		||||
    assert(src, "src is nil")
 | 
			
		||||
    local strSrc = tostring(src)
 | 
			
		||||
    Clothing.Players[strSrc] = nil
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
--- Event handler for when the resource starts
 | 
			
		||||
--- Caches appearance data for all currently connected players
 | 
			
		||||
AddEventHandler('onResourceStart', function(resource)
 | 
			
		||||
    if resource ~= GetCurrentResourceName() then return end
 | 
			
		||||
    for _, playerId in ipairs(GetPlayers()) do
 | 
			
		||||
        local src = tonumber(playerId)
 | 
			
		||||
        local strSrc = tostring(src)
 | 
			
		||||
        if not Clothing.Players[strSrc] then
 | 
			
		||||
            Clothing.Players[strSrc] = Clothing.GetAppearance(src)
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
--- Callback handler for retrieving a player's appearance data
 | 
			
		||||
Callback.Register('community_bridge:cb:GetAppearance', function(source)
 | 
			
		||||
    local src = source
 | 
			
		||||
    return Clothing.GetAppearance(src)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
--[[
 | 
			
		||||
RegisterCommand('clothing:debug', function(source, args, rawCommand)
 | 
			
		||||
    local src = source
 | 
			
		||||
    Clothing.SetAppearance(src, {
 | 
			
		||||
        components ={
 | 
			
		||||
            {component_id = 1, drawable = math.random(0, 50), texture = 0},
 | 
			
		||||
            {component_id = 2, drawable = math.random(0, 50), texture = 0},
 | 
			
		||||
            {component_id = 3, drawable = math.random(0, 50), texture = 0},
 | 
			
		||||
            {component_id = 4, drawable = math.random(0, 50), texture = 0},
 | 
			
		||||
            {component_id = 5, drawable = math.random(0, 50), texture = 0},
 | 
			
		||||
            {component_id = 6, drawable = math.random(0, 50), texture = 0},
 | 
			
		||||
            {component_id = 7, drawable = math.random(0, 50), texture = 0},
 | 
			
		||||
            {component_id = 8, drawable = math.random(0, 50), texture = 0},
 | 
			
		||||
        },
 | 
			
		||||
        props = {
 | 
			
		||||
            {prop_id = 3, drawable = 0, texture = 0},
 | 
			
		||||
            {prop_id = 1, drawable = 0, texture = 0},
 | 
			
		||||
            {prop_id = 2, drawable = 0, texture = 0},
 | 
			
		||||
        }
 | 
			
		||||
    }, false, true)
 | 
			
		||||
end, false)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
RegisterCommand('clothing:revert', function(source, args, rawCommand)
 | 
			
		||||
    local src = source
 | 
			
		||||
    Clothing.Revert(src)
 | 
			
		||||
end, false)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
RegisterCommand('clothing:current', function(source, args, rawCommand)
 | 
			
		||||
    local src = source
 | 
			
		||||
    local currentClothing = Clothing.GetAppearance(src)
 | 
			
		||||
    if not currentClothing then return end
 | 
			
		||||
    print(json.encode(currentClothing, { indent = true }))
 | 
			
		||||
end, false)
 | 
			
		||||
 | 
			
		||||
RegisterCommand('clothing:openmenu', function(source, args, rawCommand)
 | 
			
		||||
    local src = source
 | 
			
		||||
    Clothing.OpenMenu(src)
 | 
			
		||||
end, false)
 | 
			
		||||
--]]
 | 
			
		||||
 | 
			
		||||
-- RegisterCommand('clothing:crowley', function(source, args, rawCommand)
 | 
			
		||||
--     local src = source
 | 
			
		||||
--     Clothing.SetAppearance(src, {
 | 
			
		||||
--         components = {
 | 
			
		||||
--             {drawable = 0, texture = 0, component_id = 0},
 | 
			
		||||
--             {drawable = 0, texture = 0, component_id = 1},
 | 
			
		||||
--             {drawable = 19, texture = 0, component_id = 2},
 | 
			
		||||
--             {drawable = 6, texture = 0, component_id = 3},
 | 
			
		||||
--             {drawable = 0, texture = 0, component_id = 4},
 | 
			
		||||
--             {drawable = 0, texture = 0, component_id = 5},
 | 
			
		||||
--             {drawable = 0, texture = 0, component_id = 6},
 | 
			
		||||
--             {drawable = 0, texture = 0, component_id = 7},
 | 
			
		||||
--             {drawable = 23, texture = 0, component_id = 8},
 | 
			
		||||
--             {drawable = 0, texture = 0, component_id = 9},
 | 
			
		||||
--             {drawable = 0, texture = 0, component_id = 10},
 | 
			
		||||
--             {drawable = 4, texture = 2, component_id = 11}
 | 
			
		||||
--         },
 | 
			
		||||
--         props = {
 | 
			
		||||
--             {drawable = 27, prop_id = 0, texture = 0},
 | 
			
		||||
--             {drawable = 0, prop_id = 1, texture = 0},
 | 
			
		||||
--             {drawable = 0, prop_id = 2, texture = 0},
 | 
			
		||||
--             {drawable = 0, prop_id = 3, texture = 0},
 | 
			
		||||
--             {drawable = 0, prop_id = 4, texture = 0},
 | 
			
		||||
--             {drawable = 0, prop_id = 5, texture = 0},
 | 
			
		||||
--             -- {drawable = 0, prop_id = 6, texture = 0},
 | 
			
		||||
--             -- {drawable = 0, prop_id = 7, texture = 0},
 | 
			
		||||
--         }
 | 
			
		||||
--     }, false, true)
 | 
			
		||||
-- end, false)
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,188 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
 | 
			
		||||
if GetResourceState('qb-clothing') == 'missing' then return end
 | 
			
		||||
if GetResourceState('rcore_clothing') ~= 'missing' then return end
 | 
			
		||||
 | 
			
		||||
Clothing = Clothing or {}
 | 
			
		||||
 | 
			
		||||
Components = {}
 | 
			
		||||
Components.Map = {
 | 
			
		||||
    [1] = "mask",
 | 
			
		||||
    [2] = "hair",
 | 
			
		||||
    [3] = "arms",
 | 
			
		||||
    [4] = "pants",
 | 
			
		||||
    [5] = "bag",
 | 
			
		||||
    [6] = "shoes",
 | 
			
		||||
    [7] = "accessory",
 | 
			
		||||
    [8] = "t-shirt",
 | 
			
		||||
    [9] = "vest",
 | 
			
		||||
    [10] = "decals",
 | 
			
		||||
    [11] = "torso2"
 | 
			
		||||
}
 | 
			
		||||
Components.InverseMap = {
 | 
			
		||||
    mask = 1,
 | 
			
		||||
    hair = 2,
 | 
			
		||||
    arms = 3,
 | 
			
		||||
    pants = 4,
 | 
			
		||||
    bag = 5,
 | 
			
		||||
    shoes = 6,
 | 
			
		||||
    accessory = 7,
 | 
			
		||||
    ['t-shirt'] = 8, --<--I HATE THAT
 | 
			
		||||
    vest = 9,
 | 
			
		||||
    decals = 10,
 | 
			
		||||
    torso2 = 11
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Props = {}
 | 
			
		||||
Props.Map = {
 | 
			
		||||
    [0] = "hat",
 | 
			
		||||
    [1] = "glass",
 | 
			
		||||
    [2] = "ear",
 | 
			
		||||
    [6] = "watch",
 | 
			
		||||
    [7] = "bracelet"
 | 
			
		||||
}
 | 
			
		||||
Props.InverseMap = {
 | 
			
		||||
    hat = 0,
 | 
			
		||||
    glass = 1,
 | 
			
		||||
    ear = 2,
 | 
			
		||||
    watch = 6,
 | 
			
		||||
    bracelet = 7
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function Components.ConvertFromDefault(defaultComponents)
 | 
			
		||||
    local returnComponents = {}
 | 
			
		||||
    for index, componentData in pairs(defaultComponents or {}) do
 | 
			
		||||
        local componentId = Components.Map[componentData.component_id]
 | 
			
		||||
        if componentId then
 | 
			
		||||
            returnComponents[componentId] = {
 | 
			
		||||
                item = componentData.drawable,
 | 
			
		||||
                texture = componentData.texture
 | 
			
		||||
            }
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
    return returnComponents
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function Components.ConvertToDefault(qbComponents)
 | 
			
		||||
    local returnComponents = {}
 | 
			
		||||
    for componentIndex, componentData in pairs(qbComponents or {}) do
 | 
			
		||||
        local componentId = Components.InverseMap[componentIndex]
 | 
			
		||||
        if componentId then
 | 
			
		||||
            returnComponents[componentId] = {
 | 
			
		||||
                component_id = componentId,
 | 
			
		||||
                drawable = componentData.item,
 | 
			
		||||
                texture = componentData.texture
 | 
			
		||||
            }
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
    return returnComponents
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function Props.ConvertFromDefault(defaultProps)
 | 
			
		||||
    local returnProps = {}
 | 
			
		||||
    for index, propData in pairs(defaultProps or {}) do
 | 
			
		||||
        local propId = Props.Map[propData.prop_id]
 | 
			
		||||
        if propId then
 | 
			
		||||
            returnProps[propId] = {
 | 
			
		||||
                item = propData.drawable,
 | 
			
		||||
                texture = propData.texture
 | 
			
		||||
            }
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
    return returnProps
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function Props.ConvertToDefault(qbProps)
 | 
			
		||||
    local returnProps = {}
 | 
			
		||||
    for propIndex, propData in pairs(qbProps or {}) do
 | 
			
		||||
        local propId = Props.InverseMap[propIndex]
 | 
			
		||||
        if propId then
 | 
			
		||||
            table.insert(returnProps, {
 | 
			
		||||
                prop_id = propId,
 | 
			
		||||
                drawable = propData.item,
 | 
			
		||||
                texture = propData.texture
 | 
			
		||||
            })
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
    table.sort(returnProps, function(a, b)
 | 
			
		||||
        return a.prop_id < b.prop_id
 | 
			
		||||
    end)
 | 
			
		||||
    return returnProps
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function Clothing.ConvertFromDefault(defaultClothing)
 | 
			
		||||
    local components = Components.ConvertFromDefault(defaultClothing.components)
 | 
			
		||||
    local props = Props.ConvertFromDefault(defaultClothing.props)
 | 
			
		||||
 | 
			
		||||
    for propsIndex, propData in pairs(props) do
 | 
			
		||||
        components[propsIndex] = propData
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    return components --skin
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function Clothing.ConvertToDefault(qbClothing)
 | 
			
		||||
    local components = Components.ConvertToDefault(qbClothing)
 | 
			
		||||
    local props = Props.ConvertToDefault(qbClothing)
 | 
			
		||||
    return { components = components, props = props }
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Clothing = {}
 | 
			
		||||
 | 
			
		||||
-- StoredOldClothing = {}
 | 
			
		||||
 | 
			
		||||
-- Clothing.SetAppearance = function(clothingData)
 | 
			
		||||
--     if GetEntityModel(cache.ped) == `mp_m_freemode_01` then
 | 
			
		||||
--         clothingData = clothingData.male
 | 
			
		||||
--     else
 | 
			
		||||
--         clothingData = clothingData.female
 | 
			
		||||
--     end
 | 
			
		||||
--     local repackedTable = {}
 | 
			
		||||
--     local componentMap = {
 | 
			
		||||
--         [1] = "mask",
 | 
			
		||||
--         [3] = "arms",
 | 
			
		||||
--         [4] = "pants",
 | 
			
		||||
--         [5] = "bag",
 | 
			
		||||
--         [6] = "shoes",
 | 
			
		||||
--         [7] = "accessory",
 | 
			
		||||
--         [8] = "t-shirt",
 | 
			
		||||
--         [9] = "vest",
 | 
			
		||||
--         [10] = "decals",
 | 
			
		||||
--         [11] = "torso2"
 | 
			
		||||
--     }
 | 
			
		||||
 | 
			
		||||
--     local propMap = {
 | 
			
		||||
--         [0] = "hat",
 | 
			
		||||
--         [1] = "glass",
 | 
			
		||||
--         [2] = "ear",
 | 
			
		||||
--         [6] = "watch",
 | 
			
		||||
--         [7] = "bracelet"
 | 
			
		||||
--     }
 | 
			
		||||
 | 
			
		||||
--     local specialMap = {
 | 
			
		||||
--         eye_color_id = "eye_color",
 | 
			
		||||
--         moles_id = "moles",
 | 
			
		||||
--         ageing_id = "ageing",
 | 
			
		||||
--         hair_id = "hair",
 | 
			
		||||
--         face_id = "face"
 | 
			
		||||
--     }
 | 
			
		||||
 | 
			
		||||
--     for _, data in pairs(clothingData) do
 | 
			
		||||
--         if componentMap[data.component_id] then
 | 
			
		||||
--             repackedTable[componentMap[data.component_id]] = {drawable = data.drawable, texture = data.texture}
 | 
			
		||||
--         elseif propMap[data.prop_id] then
 | 
			
		||||
--             repackedTable[propMap[data.prop_id]] = {drawable = data.drawable, texture = data.texture}
 | 
			
		||||
--         elseif specialMap[data.eye_color_id] then
 | 
			
		||||
--             repackedTable[specialMap[data.eye_color_id]] = {drawable = data.drawable, texture = data.texture}
 | 
			
		||||
--         elseif specialMap[data.moles_id] then
 | 
			
		||||
--             repackedTable[specialMap[data.moles_id]] = {drawable = data.drawable, texture = data.texture}
 | 
			
		||||
--         elseif specialMap[data.ageing_id] then
 | 
			
		||||
--             repackedTable[specialMap[data.ageing_id]] = {drawable = data.drawable, texture = data.texture}
 | 
			
		||||
--         elseif specialMap[data.hair_id] then
 | 
			
		||||
--             repackedTable[specialMap[data.hair_id]] = {drawable = data.drawable, texture = data.texture}
 | 
			
		||||
--         elseif specialMap[data.face_id] then
 | 
			
		||||
--             repackedTable[specialMap[data.face_id]] = {drawable = data.drawable, texture = data.texture}
 | 
			
		||||
--         end
 | 
			
		||||
--     end
 | 
			
		||||
--     TriggerEvent('qb-clothing:client:loadOutfit', repackedTable)
 | 
			
		||||
-- end
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,7 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
if GetResourceState('rcore_clothing') == 'missing' then return end
 | 
			
		||||
Clothing = Clothing or {}
 | 
			
		||||
 | 
			
		||||
function Clothing.OpenMenu()
 | 
			
		||||
    TriggerEvent('qb-clothing:client:openMenu')
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,158 @@
 | 
			
		|||
--[[This module is incomplete]]--
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
local promises = {}
 | 
			
		||||
local activeDialogue = nil
 | 
			
		||||
local pendingCameraDestroy = false
 | 
			
		||||
Dialogue = {}
 | 
			
		||||
 | 
			
		||||
local cam = nil
 | 
			
		||||
local npc = nil
 | 
			
		||||
 | 
			
		||||
function Dialogue.Close(name)
 | 
			
		||||
    -- Instead of destroying immediately, wait to see if new dialogue opens
 | 
			
		||||
    pendingCameraDestroy = true
 | 
			
		||||
    activeDialogue = nil
 | 
			
		||||
 | 
			
		||||
    SetNuiFocus(false, false)
 | 
			
		||||
    SendNUIMessage({
 | 
			
		||||
        type = "close",
 | 
			
		||||
        name = name
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    -- Wait brief moment to see if new dialogue opens
 | 
			
		||||
    CreateThread(function()
 | 
			
		||||
        Wait(50) -- Small delay to allow new dialogue to open
 | 
			
		||||
        if pendingCameraDestroy and not activeDialogue then
 | 
			
		||||
            -- No new dialogue opened, safe to destroy camera
 | 
			
		||||
            RenderScriptCams(false, 1, 1000, 1, 0)
 | 
			
		||||
            SetCamActive(cam, false)
 | 
			
		||||
            DestroyCam(cam, false)
 | 
			
		||||
            cam = nil
 | 
			
		||||
        end
 | 
			
		||||
    end)
 | 
			
		||||
 | 
			
		||||
    promises[name] = nil
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
--- Open a dialogue with the player
 | 
			
		||||
---@param name string
 | 
			
		||||
---@param dialogue string
 | 
			
		||||
---@param options table example = {{  id = string, label = string}}
 | 
			
		||||
function Dialogue.Open( name, dialogue, characterOptions, dialogueOptions, onSelected)
 | 
			
		||||
    assert(name, "Name is required")
 | 
			
		||||
    assert(dialogue, "Dialogue is required")
 | 
			
		||||
    assert(dialogueOptions, "Dialogue options are required")
 | 
			
		||||
    assert(characterOptions, "CharacterOptions must be a number or table containing an entity")
 | 
			
		||||
    local isCharacterATable = type(characterOptions) == "table"
 | 
			
		||||
    local entity = isCharacterATable and characterOptions.entity or tonumber(characterOptions)
 | 
			
		||||
    local offset = isCharacterATable and characterOptions.offset or vector3(0, 0, 0)
 | 
			
		||||
    local rotationOffset = isCharacterATable and characterOptions.rotationOffset or vector3(0, 0, 0)
 | 
			
		||||
 | 
			
		||||
    -- Cancel any pending camera destroy
 | 
			
		||||
    pendingCameraDestroy = false
 | 
			
		||||
    activeDialogue = name
 | 
			
		||||
 | 
			
		||||
    -- camera magic!
 | 
			
		||||
    if entity then
 | 
			
		||||
        Wait(500)
 | 
			
		||||
        local endLocation = GetOffsetFromEntityInWorldCoords(entity, offset.x, offset.y + 2.0, offset.z + 0.5)
 | 
			
		||||
        local pedHeading = GetEntityHeading(entity)
 | 
			
		||||
        -- Get position in front of ped based on their heading
 | 
			
		||||
 | 
			
		||||
        if not cam then cam = CreateCam("DEFAULT_SCRIPTED_CAMERA", 1) end
 | 
			
		||||
        local camAngle = (pedHeading + 180.0) % 360.0
 | 
			
		||||
        SetCamRot(cam, rotationOffset.x, rotationOffset.y, camAngle + rotationOffset.z, 2)
 | 
			
		||||
        SetCamCoord(cam, endLocation.x, endLocation.y, endLocation.z)
 | 
			
		||||
        RenderScriptCams(true, true, 1000, true, false)
 | 
			
		||||
        SetCamActive(cam, true)
 | 
			
		||||
 | 
			
		||||
    end
 | 
			
		||||
    SendNUIMessage({
 | 
			
		||||
        type = "open",
 | 
			
		||||
        text =  dialogue,
 | 
			
		||||
        name = name,
 | 
			
		||||
        options = dialogueOptions
 | 
			
		||||
    })
 | 
			
		||||
    SetNuiFocus(true, true)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    local prom = promise.new()
 | 
			
		||||
    local wrappedFunction = function(selected)
 | 
			
		||||
        SetNuiFocus(false, false)
 | 
			
		||||
        Dialogue.Close(name)
 | 
			
		||||
        if onSelected then onSelected(selected) end
 | 
			
		||||
        prom:resolve(selected)
 | 
			
		||||
    end
 | 
			
		||||
    promises[name] = wrappedFunction
 | 
			
		||||
    return Citizen.Await(prom)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
RegisterNuiCallback("dialogue:SelectOption", function(data)
 | 
			
		||||
    local promis = promises[data.name]
 | 
			
		||||
    if not promis then return end
 | 
			
		||||
    promis(data.id)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
-- Debug command
 | 
			
		||||
if BridgeSharedConfig.DebugLevel  >= 1 then
 | 
			
		||||
    -- RegisterCommand("dialogue", function()
 | 
			
		||||
    --     local pos = GetOffsetFromEntityInWorldCoords(PlayerPedId(), 0, 2.0, 0)
 | 
			
		||||
    --     local timeout = 500
 | 
			
		||||
    --     local model = `a_f_y_hipster_01`
 | 
			
		||||
    --     RequestModel(model)
 | 
			
		||||
    --     while not HasModelLoaded(model) do
 | 
			
		||||
    --         Wait(0)
 | 
			
		||||
    --         timeout = timeout - 1
 | 
			
		||||
    --         if timeout == 0 then
 | 
			
		||||
    --             print("Failed to load model")
 | 
			
		||||
    --             return
 | 
			
		||||
    --         end
 | 
			
		||||
    --     end
 | 
			
		||||
    --     local ped = CreatePed(0, model, pos.x, pos.y, pos.z, 0.0, false, false)
 | 
			
		||||
 | 
			
		||||
    --     local characterData = {
 | 
			
		||||
    --         entity = ped,
 | 
			
		||||
    --         offset = vector3(0, 0, 0),
 | 
			
		||||
    --         rotationOffset = vector3(0, 0, 0)
 | 
			
		||||
    --     }
 | 
			
		||||
    --     Wait(750)
 | 
			
		||||
    --     Dialogue.Open("Akmed", "Hello how are you doing my friend?", characterData, {
 | 
			
		||||
    --         {
 | 
			
		||||
    --             label = "Trade with me",
 | 
			
		||||
    --             id = 'something',
 | 
			
		||||
    --         },
 | 
			
		||||
    --         {
 | 
			
		||||
    --             label = "Goodbye",
 | 
			
		||||
    --             id = 'someotherthing',
 | 
			
		||||
    --         },
 | 
			
		||||
    --     },
 | 
			
		||||
    --     function(selectedId)
 | 
			
		||||
    --         if selectedId == 'something' then
 | 
			
		||||
    --             Dialogue.Open( "Akmed" , "Thank you for wanting to purchase me lucky charms", characterData, {
 | 
			
		||||
    --                 {
 | 
			
		||||
    --                     label = "Fuck off",
 | 
			
		||||
    --                     id = 'something',
 | 
			
		||||
    --                 },
 | 
			
		||||
    --                 {
 | 
			
		||||
    --                     label = "Goodbye",
 | 
			
		||||
    --                     id = 'someotherthing',
 | 
			
		||||
    --                 },
 | 
			
		||||
    --             },
 | 
			
		||||
    --             function(selectedId)
 | 
			
		||||
    --                 DeleteEntity(ped)
 | 
			
		||||
    --                 if selectedId == "something" then
 | 
			
		||||
    --                     print("You hate lucky charms")
 | 
			
		||||
    --                 else
 | 
			
		||||
    --                     print("Thanks for keeping it civil")
 | 
			
		||||
    --                 end
 | 
			
		||||
    --             end)
 | 
			
		||||
    --         else
 | 
			
		||||
    --             DeleteEntity(ped)
 | 
			
		||||
    --         end
 | 
			
		||||
    --     end)
 | 
			
		||||
    -- end)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return Dialogue
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,32 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
Dispatch = Dispatch or {}
 | 
			
		||||
 | 
			
		||||
---This will send an alert to currently supported dispatch systems.
 | 
			
		||||
---@param data table The data to send to the dispatch system.
 | 
			
		||||
---@return nil
 | 
			
		||||
Dispatch.SendAlert = function(data)
 | 
			
		||||
    TriggerServerEvent('community_bridge:Server:DispatchAlert', {
 | 
			
		||||
        sprite = data.blipData.sprite or 161,
 | 
			
		||||
        color = data.blipData.color or 1,
 | 
			
		||||
        scale = data.blipData.scale or 0.8,
 | 
			
		||||
        vehicle = data.vehicle or nil,
 | 
			
		||||
        plate = data.vehicle and GetVehicleNumberPlateText(data.vehicle) or nil,
 | 
			
		||||
        ped = data.ped or cache.ped,
 | 
			
		||||
        pedCoords = data.pedCoords or GetEntityCoords(cache.ped),
 | 
			
		||||
        coords = data.coords or GetEntityCoords(cache.ped),
 | 
			
		||||
        message = data.message or "An Alert Has Been Made",
 | 
			
		||||
        code = data.code or '10-80',
 | 
			
		||||
        icon = data.icon or 'fas fa-question',
 | 
			
		||||
        jobs = data.jobs or {'police'},
 | 
			
		||||
        time = data.time or 100000
 | 
			
		||||
    })
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
RegisterNetEvent('community_bridge:Client:DispatchAlert', function(alert)
 | 
			
		||||
    Notify.SendNotify(alert.message, "success", 15000)
 | 
			
		||||
    local blip = Bridge.Utility.CreateBlip(alert.coords, alert.sprite, alert.color, alert.scale, alert.code, true)
 | 
			
		||||
	Wait(alert.time)
 | 
			
		||||
    Bridge.Utility.RemoveBlip(blip)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
return Dispatch
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,13 @@
 | 
			
		|||
Dispatch = Dispatch or {}
 | 
			
		||||
 | 
			
		||||
RegisterNetEvent("community_bridge:Server:DispatchAlert", function(data)
 | 
			
		||||
    local jobs = data.jobs
 | 
			
		||||
    for _, name in pairs(jobs) do
 | 
			
		||||
        local activeJobPlayers = Bridge.Framework.GetPlayersByJob(name)
 | 
			
		||||
        for _, src in pairs(activeJobPlayers) do
 | 
			
		||||
            TriggerClientEvent('community_bridge:Client:DispatchAlert', src, data)
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
return Dispatch
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,18 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
if GetResourceState('bub-mdt') == 'missing' then return end
 | 
			
		||||
Dispatch = Dispatch or {}
 | 
			
		||||
 | 
			
		||||
Dispatch.SendAlert = function(data)
 | 
			
		||||
    local alertData = {
 | 
			
		||||
        code = data.code or '10-80',
 | 
			
		||||
        offense = data.message,
 | 
			
		||||
        coords = data.coords or GetEntityCoords(cache.ped),
 | 
			
		||||
        info = { label = data.code or '10-80', icon = data.icon or 'fas fa-question' },
 | 
			
		||||
        blip = data.blipData.sprite or 1,
 | 
			
		||||
        isEmergency = data.priority == 1 and true or false,
 | 
			
		||||
        blipCoords = data.coords or cache.ped and GetEntityCoords(cache.ped) or { x = 0, y = 0},
 | 
			
		||||
    }
 | 
			
		||||
    exports["bub-mdt"]:CustomAlert(alertData)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return Dispatch
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,4 @@
 | 
			
		|||
if GetResourceState('bub-mdt') == 'missing' then return end
 | 
			
		||||
Dispatch = Dispatch or {}
 | 
			
		||||
 | 
			
		||||
return Dispatch
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,27 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
if GetResourceState('cd_dispatch') == 'missing' then return end
 | 
			
		||||
Dispatch = Dispatch or {}
 | 
			
		||||
 | 
			
		||||
Dispatch.SendAlert = function(data)
 | 
			
		||||
    local plyrData = exports['cd_dispatch']:GetPlayerInfo()
 | 
			
		||||
    TriggerServerEvent('cd_dispatch:AddNotification', {
 | 
			
		||||
        job_table = data.jobs,
 | 
			
		||||
        coords = data.coords,
 | 
			
		||||
        title = data.message,
 | 
			
		||||
        message = data.message,
 | 
			
		||||
        flash = 0,
 | 
			
		||||
        unique_id = plyrData.unique_id,
 | 
			
		||||
        sound = 1,
 | 
			
		||||
        blip = {
 | 
			
		||||
            sprite = data.blipData.sprite,
 | 
			
		||||
            scale = data.blipData.scale,
 | 
			
		||||
            colour = data.blipData.color,
 | 
			
		||||
            flashes = false,
 | 
			
		||||
            text = data.message,
 | 
			
		||||
            time = (data.time / 1000),
 | 
			
		||||
            radius = 0,
 | 
			
		||||
        }
 | 
			
		||||
    })
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return Dispatch
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,4 @@
 | 
			
		|||
if GetResourceState('cd_dispatch') == 'missing' then return end
 | 
			
		||||
Dispatch = Dispatch or {}
 | 
			
		||||
 | 
			
		||||
return Dispatch
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,30 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
if GetResourceState('kartik-mdt') == 'missing' then return end
 | 
			
		||||
Dispatch = Dispatch or {}
 | 
			
		||||
 | 
			
		||||
Dispatch.SendAlert = function(data)
 | 
			
		||||
    local repackJobsBools = {}
 | 
			
		||||
    for k, v in pairs(data.jobs) do
 | 
			
		||||
        if v then
 | 
			
		||||
            repackJobsBools[k] = true
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
    local alertOptions = {
 | 
			
		||||
        title = data.message or "Alert",
 | 
			
		||||
        code = data.code or '10-80',
 | 
			
		||||
        description = data.message,
 | 
			
		||||
        type = "Alert",
 | 
			
		||||
        coords = data.coords,
 | 
			
		||||
        blip = {
 | 
			
		||||
            radius = 100.0,
 | 
			
		||||
            sprite = data.blipData.sprite or 161,
 | 
			
		||||
            color = data.blipData.color or 1,
 | 
			
		||||
            scale = data.blipData.scale or 0.8,
 | 
			
		||||
            length = 2
 | 
			
		||||
        },
 | 
			
		||||
        jobs = repackJobsBools,
 | 
			
		||||
    }
 | 
			
		||||
    exports['kartik-mdt']:CustomAlert(alertOptions)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return Dispatch
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,4 @@
 | 
			
		|||
if GetResourceState('kartik-mdt') == 'missing' then return end
 | 
			
		||||
Dispatch = Dispatch or {}
 | 
			
		||||
 | 
			
		||||
return Dispatch
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,43 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
if GetResourceState('lb-tablet') == 'missing' then return end
 | 
			
		||||
Dispatch = Dispatch or {}
 | 
			
		||||
 | 
			
		||||
local function getPriorityLevel(priority)
 | 
			
		||||
    if priority == 1 then
 | 
			
		||||
        return 'low'
 | 
			
		||||
    elseif priority == 2 then
 | 
			
		||||
        return 'medium'
 | 
			
		||||
    elseif priority == 3 then
 | 
			
		||||
        return 'high'
 | 
			
		||||
    else
 | 
			
		||||
        return 'medium'
 | 
			
		||||
    end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will send an alert to the passed jobs
 | 
			
		||||
---@param data table
 | 
			
		||||
Dispatch.SendAlert = function(data)
 | 
			
		||||
    local streetName, _ = Utility.GetStreetNameAtCoords(data.coords)
 | 
			
		||||
    local priority = getPriorityLevel(data.priority)
 | 
			
		||||
    if type(data.jobs) == 'table' then
 | 
			
		||||
        data.jobs = data.jobs[1]
 | 
			
		||||
    end
 | 
			
		||||
    if data.time and data.time > 1000 then
 | 
			
		||||
        data.time = math.floor((data.time / 1000) + 0.5)
 | 
			
		||||
    end
 | 
			
		||||
    local alertData = {
 | 
			
		||||
        priority = priority,
 | 
			
		||||
        code = data.code or '10-80',
 | 
			
		||||
        title = 'Dispatch Alert!',
 | 
			
		||||
        description = data.message,
 | 
			
		||||
        location = {
 | 
			
		||||
            label = streetName,
 | 
			
		||||
            coords = vec2(data.coords.x, data.coords.y)
 | 
			
		||||
        },
 | 
			
		||||
        time = data.time or 10000,
 | 
			
		||||
        job = data.jobs,
 | 
			
		||||
    }
 | 
			
		||||
    TriggerServerEvent("community_bridge:server:dispatch:sendAlert", alertData)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return Dispatch
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,8 @@
 | 
			
		|||
if GetResourceState('lb-tablet') == 'missing' then return end
 | 
			
		||||
Dispatch = Dispatch or {}
 | 
			
		||||
 | 
			
		||||
RegisterNetEvent("community_bridge:server:dispatch:sendAlert", function(data)
 | 
			
		||||
    exports["lb-tablet"]:AddDispatch(data) -- this has a return value but we dont really have a use for it atm.
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
return Dispatch
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,21 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
if GetResourceState('linden_outlawalert') == 'missing' then return end
 | 
			
		||||
Dispatch = Dispatch or {}
 | 
			
		||||
 | 
			
		||||
Dispatch.SendAlert = function(data)
 | 
			
		||||
    TriggerServerEvent('wf-alerts:svNotify', {
 | 
			
		||||
        dispatchData = {
 | 
			
		||||
            displayCode = data.code or '211',
 | 
			
		||||
            description = data.message or "Alert",
 | 
			
		||||
            isImportant = 0,
 | 
			
		||||
            recipientList = data.jobs or {'police'},
 | 
			
		||||
            length = data.time or '10000',
 | 
			
		||||
            infoM = data.icon or 'fas fa-question',
 | 
			
		||||
            info = data.message or "Alert"
 | 
			
		||||
        },
 | 
			
		||||
        caller = 'Anonymous',
 | 
			
		||||
        coords = data.coords or GetEntityCoords(cache.ped)
 | 
			
		||||
    })
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return Dispatch
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,4 @@
 | 
			
		|||
if GetResourceState('linden_outlawalert') == 'missing' then return end
 | 
			
		||||
Dispatch = Dispatch or {}
 | 
			
		||||
 | 
			
		||||
return Dispatch
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,27 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
if GetResourceState('origen_police') == 'missing' then return end
 | 
			
		||||
Dispatch = Dispatch or {}
 | 
			
		||||
 | 
			
		||||
Dispatch.SendAlert = function(data)
 | 
			
		||||
    local color = nil
 | 
			
		||||
    if data.vehicle then
 | 
			
		||||
        local r, g, b = GetVehicleColor(data.vehicle)
 | 
			
		||||
        color = {r, g, b}
 | 
			
		||||
    end
 | 
			
		||||
    local customData = {
 | 
			
		||||
        coords = data.coords or vector3(0.0, 0.0, 0.0),
 | 
			
		||||
        title = 'Alert '..(data.code or '10-80'),
 | 
			
		||||
        message = data.message,
 | 
			
		||||
        job = data.jobs or 'police',
 | 
			
		||||
        metadata = {
 | 
			
		||||
            model = data.vehicle and (GetDisplayNameFromVehicleModel(GetEntityModel(data.vehicle))) or nil,
 | 
			
		||||
            color = color,
 | 
			
		||||
            plate = data.vehicle and GetVehicleNumberPlateText(data.vehicle) or nil,
 | 
			
		||||
            speed = data.vehicle and (GetEntitySpeed(veh) * 3.6)..' kmh' or nil
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    TriggerServerEvent("SendAlert:police", customData)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return Dispatch
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,4 @@
 | 
			
		|||
if GetResourceState('origen_police') == 'missing' then return end
 | 
			
		||||
Dispatch = Dispatch or {}
 | 
			
		||||
 | 
			
		||||
return Dispatch
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,33 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
if GetResourceState('ps-dispatch') == 'missing' then return end
 | 
			
		||||
if GetResourceState('lb-tablet') == 'started' then return end
 | 
			
		||||
Dispatch = Dispatch or {}
 | 
			
		||||
 | 
			
		||||
Dispatch.SendAlert = function(data)
 | 
			
		||||
    local alertData = {
 | 
			
		||||
        message = data.message,
 | 
			
		||||
        code = data.code or '10-80',
 | 
			
		||||
        icon = data.icon or 'fas fa-question',
 | 
			
		||||
        priority = 2,
 | 
			
		||||
        coords = data.coords,
 | 
			
		||||
        vehicle = data.vehicle,
 | 
			
		||||
        plate = data.plate,
 | 
			
		||||
        alertTime = (data.time or 10000) / 1000,
 | 
			
		||||
        alert = {
 | 
			
		||||
            radius = 0,
 | 
			
		||||
            recipientList = data.jobs,
 | 
			
		||||
            sprite = data.blipData.sprite,
 | 
			
		||||
            color = data.blipData.color,
 | 
			
		||||
            scale = data.blipData.scale,
 | 
			
		||||
            length = 2,
 | 
			
		||||
            sound = "Lose_1st",
 | 
			
		||||
            sound2 = "GTAO_FM_Events_Soundset",
 | 
			
		||||
            offset = false,
 | 
			
		||||
            flash = false
 | 
			
		||||
        },
 | 
			
		||||
        jobs = data.jobs
 | 
			
		||||
    }
 | 
			
		||||
    exports["ps-dispatch"]:CustomAlert(alertData)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return Dispatch
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,5 @@
 | 
			
		|||
if GetResourceState('ps-dispatch') == 'missing' then return end
 | 
			
		||||
if GetResourceState('lb-tablet') == 'started' then return end
 | 
			
		||||
Dispatch = Dispatch or {}
 | 
			
		||||
 | 
			
		||||
return Dispatch
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,41 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
if GetResourceState('qs-dispatch') == 'missing' then return end
 | 
			
		||||
Dispatch = Dispatch or {}
 | 
			
		||||
 | 
			
		||||
Dispatch.SendAlert = function(data)
 | 
			
		||||
    local playerData = exports['qs-dispatch']:GetPlayerInfo()
 | 
			
		||||
    if not playerData then return print("Error getting player data") end
 | 
			
		||||
 | 
			
		||||
    local customData = {
 | 
			
		||||
        job = data.jobs or { 'police'},
 | 
			
		||||
        callLocation = data.coords or vec3(0.0, 0.0, 0.0),
 | 
			
		||||
        callCode = {
 | 
			
		||||
            code = data.code or '10-80',
 | 
			
		||||
            snippet = data.snippet or 'General Alert'
 | 
			
		||||
        },
 | 
			
		||||
        message = data.message,
 | 
			
		||||
        flashes = false,
 | 
			
		||||
        image = nil,
 | 
			
		||||
        blip = {
 | 
			
		||||
            sprite = data.blipData.sprite or 1,
 | 
			
		||||
            scale = data.blipData.scale or 1.0,
 | 
			
		||||
            colour = data.blipData.color or 1,
 | 
			
		||||
            flashes = false,
 | 
			
		||||
            text = data.message or "Alert",
 | 
			
		||||
            time = data.length and (data.time * 1000) or 20000
 | 
			
		||||
        },
 | 
			
		||||
        otherData = {
 | 
			
		||||
            {
 | 
			
		||||
                text = data.name or 'N/A',
 | 
			
		||||
                icon = data.icon or 'fas fa-question'
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    exports['qs-dispatch']:getSSURL(function(image)
 | 
			
		||||
        customData.image = image or customData.image
 | 
			
		||||
        TriggerServerEvent('qs-dispatch:server:CreateDispatchCall', customData)
 | 
			
		||||
    end)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return Dispatch
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,4 @@
 | 
			
		|||
if GetResourceState('qs-dispatch') == 'missing' then return end
 | 
			
		||||
Dispatch = Dispatch or {}
 | 
			
		||||
 | 
			
		||||
return Dispatch
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,17 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
if GetResourceState('redutzu-mdt') == 'missing' then return end
 | 
			
		||||
Dispatch = Dispatch or {}
 | 
			
		||||
 | 
			
		||||
Dispatch.SendAlert = function(data)
 | 
			
		||||
    local streetName, _ = Utility.GetStreetNameAtCoords(data.coords)
 | 
			
		||||
    local alertData = {
 | 
			
		||||
        code = data.code or '10-80',
 | 
			
		||||
        message = data.message or "Dispatch Alert",
 | 
			
		||||
        street = streetName,
 | 
			
		||||
        time = data.time or 10000,
 | 
			
		||||
        coords = data.coords,
 | 
			
		||||
    }
 | 
			
		||||
    TriggerServerEvent("community_bridge:server:dispatch:sendAlert", alertData)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return Dispatch
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,14 @@
 | 
			
		|||
if GetResourceState('redutzu-mdt') == 'missing' then return end
 | 
			
		||||
Dispatch = Dispatch or {}
 | 
			
		||||
 | 
			
		||||
RegisterNetEvent("community_bridge:server:dispatch:sendAlert", function(data)
 | 
			
		||||
    TriggerEvent('redutzu-mdt:server:addDispatchToMDT', {
 | 
			
		||||
        code = data.code,
 | 
			
		||||
        title = data.message,
 | 
			
		||||
        street = data.street,
 | 
			
		||||
        duration = data.time,
 | 
			
		||||
        coords = data.coords
 | 
			
		||||
    })
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
return Dispatch
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,23 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
if GetResourceState('tk_dispatch') == 'missing' then return end
 | 
			
		||||
Dispatch = Dispatch or {}
 | 
			
		||||
 | 
			
		||||
Dispatch.SendAlert = function(data)
 | 
			
		||||
    exports.tk_dispatch:addCall({
 | 
			
		||||
        title = data.message,
 | 
			
		||||
        code = data.code or '10-80',
 | 
			
		||||
        priority = 'Priority 3',
 | 
			
		||||
        coords = data.coords or GetEntityCoords(PlayerPedId()),
 | 
			
		||||
        showLocation = true,
 | 
			
		||||
        showGender = false,
 | 
			
		||||
        playSound = true,
 | 
			
		||||
        blip = {
 | 
			
		||||
            color = data.blipData.color or 3,
 | 
			
		||||
            sprite = data.blipData.sprite or 1,
 | 
			
		||||
            scale = data.blipData.scale or 0.8,
 | 
			
		||||
        },
 | 
			
		||||
        jobs = data.jobs or {'police'},
 | 
			
		||||
    })
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return Dispatch
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,4 @@
 | 
			
		|||
if GetResourceState('tk_dispatch') == 'missing' then return end
 | 
			
		||||
Dispatch = Dispatch or {}
 | 
			
		||||
 | 
			
		||||
return Dispatch
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,10 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
Doorlock = Doorlock or {}
 | 
			
		||||
 | 
			
		||||
---This will get the closest door to the ped
 | 
			
		||||
---@return string | nil
 | 
			
		||||
Doorlock.GetClosestDoor = function()
 | 
			
		||||
    return nil
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return Doorlock
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,13 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
 | 
			
		||||
Doorlock = Doorlock or {}
 | 
			
		||||
 | 
			
		||||
---This will toggle the lock status of the door.
 | 
			
		||||
---@param doorID string
 | 
			
		||||
---@param toggle boolean
 | 
			
		||||
---@return boolean
 | 
			
		||||
Doorlock.ToggleDoorLock = function(doorID, toggle)
 | 
			
		||||
    return true
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return Doorlock
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,12 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
if GetResourceState('doors_creator') == 'missing' then return end
 | 
			
		||||
 | 
			
		||||
Doorlock = Doorlock or {}
 | 
			
		||||
 | 
			
		||||
---This will get the closest door to the ped
 | 
			
		||||
---@return string | nil
 | 
			
		||||
Doorlock.GetClosestDoor = function()
 | 
			
		||||
    return exports["doors_creator"]:getClosestActiveDoor()
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return Doorlock
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,21 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
if GetResourceState('doors_creator') == 'missing' then return end
 | 
			
		||||
 | 
			
		||||
Doorlock = Doorlock or {}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
---This will toggle the lock status of the door.
 | 
			
		||||
---@param doorID string
 | 
			
		||||
---@param toggle boolean
 | 
			
		||||
---@return boolean
 | 
			
		||||
Doorlock.ToggleDoorLock = function(doorID, toggle)
 | 
			
		||||
    local state = toggle
 | 
			
		||||
    if state then
 | 
			
		||||
        exports["doors_creator"]:setDoorState(doorID, 1)
 | 
			
		||||
    else
 | 
			
		||||
        exports["doors_creator"]:setDoorState(doorID, 0)
 | 
			
		||||
    end
 | 
			
		||||
    return true
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return Doorlock
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,14 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
if GetResourceState('ox_doorlock') == 'missing' then return end
 | 
			
		||||
 | 
			
		||||
Doorlock = Doorlock or {}
 | 
			
		||||
 | 
			
		||||
---This will get the closest door to the ped
 | 
			
		||||
---@return string | nil
 | 
			
		||||
Doorlock.GetClosestDoor = function()
 | 
			
		||||
    local doorData = exports.ox_doorlock:getClosestDoor()
 | 
			
		||||
    if not doorData then return end
 | 
			
		||||
    return tostring(doorData.id) or nil
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return Doorlock
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,20 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
if GetResourceState('ox_doorlock') == 'missing' then return end
 | 
			
		||||
 | 
			
		||||
Doorlock = Doorlock or {}
 | 
			
		||||
 | 
			
		||||
---This will toggle the lock status of the door.
 | 
			
		||||
---@param doorID string
 | 
			
		||||
---@param toggle boolean
 | 
			
		||||
---@return boolean
 | 
			
		||||
Doorlock.ToggleDoorLock = function(doorID, toggle)
 | 
			
		||||
    local state = toggle
 | 
			
		||||
    if state then
 | 
			
		||||
        exports.ox_doorlock:setDoorState(doorID, 1)
 | 
			
		||||
    else
 | 
			
		||||
        exports.ox_doorlock:setDoorState(doorID, 0)
 | 
			
		||||
    end
 | 
			
		||||
    return true
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return Doorlock
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,25 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
if GetResourceState('qb-doorlock') == 'missing' then return end
 | 
			
		||||
 | 
			
		||||
Doorlock = Doorlock or {}
 | 
			
		||||
 | 
			
		||||
---This will get the closest door to the ped
 | 
			
		||||
---@return string | nil
 | 
			
		||||
Doorlock.GetClosestDoor = function()
 | 
			
		||||
    local closestDoor = exports["qb-doorlock"]:GetClosestDoor()
 | 
			
		||||
    if Table.CheckPopulated(closestDoor) then return closestDoor end
 | 
			
		||||
    local allDoors = exports["qb-doorlock"]:GetDoorList()
 | 
			
		||||
    local pedCoords = GetEntityCoords(cache.ped)
 | 
			
		||||
    local door = 0
 | 
			
		||||
    local doorDist = 1000.0
 | 
			
		||||
    for doorID, data in pairs(allDoors) do
 | 
			
		||||
        local dist = #(pedCoords - data.objCoords)
 | 
			
		||||
        if dist < doorDist then
 | 
			
		||||
            door = doorID
 | 
			
		||||
            doorDist = dist
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
    return door
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return Doorlock
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,15 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
if GetResourceState('qb-doorlock') == 'missing' then return end
 | 
			
		||||
 | 
			
		||||
Doorlock = Doorlock or {}
 | 
			
		||||
 | 
			
		||||
---This will toggle the lock status of the door.
 | 
			
		||||
---@param doorID string
 | 
			
		||||
---@param toggle boolean
 | 
			
		||||
---@return boolean
 | 
			
		||||
Doorlock.ToggleDoorLock = function(doorID, toggle)
 | 
			
		||||
    TriggerClientEvent('qb-doorlock:client:setState', -1, 0, doorID, toggle, false, false, false)
 | 
			
		||||
    return true
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return Doorlock
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,23 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
if GetResourceState('rcore_doorlock') == 'missing' then return end
 | 
			
		||||
 | 
			
		||||
Doorlock = Doorlock or {}
 | 
			
		||||
 | 
			
		||||
---This will get the closest door to the ped
 | 
			
		||||
---@return string | nil
 | 
			
		||||
Doorlock.GetClosestDoor = function()
 | 
			
		||||
    local allDoors = exports.rcore_doorlock:getLoadedDoors()
 | 
			
		||||
    local pedCoords = GetEntityCoords(cache.ped)
 | 
			
		||||
    local door = 0
 | 
			
		||||
    local doorDist = 1000.0
 | 
			
		||||
    for _, data in pairs(allDoors) do
 | 
			
		||||
        local dist = #(pedCoords - data.coords)
 | 
			
		||||
        if dist < doorDist then
 | 
			
		||||
            door = data.id
 | 
			
		||||
            doorDist = dist
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
    return door
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return Doorlock
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,19 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
if GetResourceState('rcore_doorlock') == 'missing' then return end
 | 
			
		||||
 | 
			
		||||
Doorlock = Doorlock or {}
 | 
			
		||||
 | 
			
		||||
---This will toggle the lock status of the door.
 | 
			
		||||
---@param doorID string
 | 
			
		||||
---@param toggle boolean
 | 
			
		||||
---@return boolean
 | 
			
		||||
Doorlock.ToggleDoorLock = function(doorID, toggle)
 | 
			
		||||
    local state = toggle
 | 
			
		||||
    if state then
 | 
			
		||||
        exports.rcore_doorlock:changeDoorState(doorID, 0)
 | 
			
		||||
    else
 | 
			
		||||
        exports.rcore_doorlock:changeDoorState(doorID, 1)
 | 
			
		||||
    end
 | 
			
		||||
    return true
 | 
			
		||||
end
 | 
			
		||||
return Doorlock
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,3 @@
 | 
			
		|||
Framework = Framework or {}
 | 
			
		||||
 | 
			
		||||
return Framework
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,3 @@
 | 
			
		|||
Framework = Framework or {}
 | 
			
		||||
 | 
			
		||||
return Framework
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,226 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
if GetResourceState('es_extended') ~= 'started' then return end
 | 
			
		||||
 | 
			
		||||
ESX = exports["es_extended"]:getSharedObject()
 | 
			
		||||
Callback = Callback or Require("lib/utility/shared/callbacks.lua")
 | 
			
		||||
 | 
			
		||||
Framework = Framework or {}
 | 
			
		||||
 | 
			
		||||
local cachedItemList = nil
 | 
			
		||||
-- This is an internal function, its here to attempt to emulate qbs shared items mainly.
 | 
			
		||||
Framework.ItemList = function()
 | 
			
		||||
    if cachedItemList then return cachedItemList end
 | 
			
		||||
    local items = Callback.Trigger('community_bridge:Callback:GetFrameworkItems', false)
 | 
			
		||||
    cachedItemList = { Items = items.Items or {} }
 | 
			
		||||
    return cachedItemList
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will get the name of the framework being used (if a supported framework).
 | 
			
		||||
---@return string
 | 
			
		||||
Framework.GetFrameworkName = function()
 | 
			
		||||
    return 'es_extended'
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return true if the player is loaded, false otherwise.
 | 
			
		||||
---This could be useful in scripts that rely on player loaded events and offer a debug mode to hit this function.
 | 
			
		||||
---@return boolean
 | 
			
		||||
Framework.GetIsPlayerLoaded = function()
 | 
			
		||||
    return ESX.IsPlayerLoaded()
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return a table of the player data, this will be in the framework format.
 | 
			
		||||
---This is mainly for internal bridge use and should be avoided.
 | 
			
		||||
---@return table
 | 
			
		||||
Framework.GetPlayerData = function()
 | 
			
		||||
    return ESX.GetPlayerData()
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return a table of all the jobs in the framework.
 | 
			
		||||
---@return table
 | 
			
		||||
Framework.GetFrameworkJobs = function()
 | 
			
		||||
    local jobs = Callback.Trigger('community_bridge:Callback:GetFrameworkJobs', false)
 | 
			
		||||
    return jobs
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return the players birth date
 | 
			
		||||
---@return string
 | 
			
		||||
Framework.GetPlayerDob = function()
 | 
			
		||||
    local playerData = Framework.GetPlayerData()
 | 
			
		||||
    local dob = playerData.dateofbirth
 | 
			
		||||
    return dob
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return the players metadata for the specified metadata key.
 | 
			
		||||
---@param metadata table | string
 | 
			
		||||
---@return table | string | number | boolean
 | 
			
		||||
Framework.GetPlayerMetaData = function(metadata)
 | 
			
		||||
    return Framework.GetPlayerData().metadata[metadata]
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will send a notification to the player.
 | 
			
		||||
---@param message string
 | 
			
		||||
---@param type string
 | 
			
		||||
---@param time number
 | 
			
		||||
---@return nil
 | 
			
		||||
Framework.Notify = function(message, type, time)
 | 
			
		||||
    return ESX.ShowNotification(message, type, time)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Will Display the help text message on the screen
 | 
			
		||||
---@param message string
 | 
			
		||||
---@param _ unknown
 | 
			
		||||
---@return nil
 | 
			
		||||
Framework.ShowHelpText = function(message, _)
 | 
			
		||||
    return exports['esx_textui']:TextUI(message, "info")
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will hide the help text message on the screen
 | 
			
		||||
---@return nil
 | 
			
		||||
Framework.HideHelpText = function()
 | 
			
		||||
    return exports['esx_textui']:HideUI()
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will get the players identifier (citizenid) etc.
 | 
			
		||||
---@return string
 | 
			
		||||
Framework.GetPlayerIdentifier = function()
 | 
			
		||||
    local playerData = Framework.GetPlayerData()
 | 
			
		||||
    return playerData.identifier
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will get the players name (first and last).
 | 
			
		||||
---@return string
 | 
			
		||||
---@return string
 | 
			
		||||
Framework.GetPlayerName = function()
 | 
			
		||||
    local playerData = Framework.GetPlayerData()
 | 
			
		||||
    return playerData.firstName, playerData.lastName
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Depricated : This will return the players job name, job label, job grade label and job grade level
 | 
			
		||||
---@return string
 | 
			
		||||
---@return string
 | 
			
		||||
---@return string
 | 
			
		||||
---@return string
 | 
			
		||||
Framework.GetPlayerJob = function()
 | 
			
		||||
    local playerData = Framework.GetPlayerData()
 | 
			
		||||
    return playerData.job.name, playerData.job.label, playerData.job.grade_label, playerData.job.grade
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return the players job name, job label, job grade label job grade level, boss status, and duty status in a table
 | 
			
		||||
---@return table
 | 
			
		||||
Framework.GetPlayerJobData = function()
 | 
			
		||||
    local playerData = Framework.GetPlayerData()
 | 
			
		||||
    local jobData = playerData.job
 | 
			
		||||
    local isBoss = (jobData.grade_name == "boss")
 | 
			
		||||
    return {
 | 
			
		||||
        jobName = jobData.name,
 | 
			
		||||
        jobLabel = jobData.label,
 | 
			
		||||
        gradeName = jobData.grade_name,
 | 
			
		||||
        gradeLabel = jobData.grade_label,
 | 
			
		||||
        gradeRank = jobData.grade,
 | 
			
		||||
        boss = isBoss,
 | 
			
		||||
        onDuty = jobData.onduty,
 | 
			
		||||
    }
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return if the player has the specified item in their inventory.
 | 
			
		||||
---@param item string
 | 
			
		||||
---@return boolean
 | 
			
		||||
Framework.HasItem = function(item)
 | 
			
		||||
	local hasItem = ESX.SearchInventory(item, true)
 | 
			
		||||
	return hasItem > 0 and true or false
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return the item count for the specified item in the players inventory.
 | 
			
		||||
---@param item string
 | 
			
		||||
---@return number
 | 
			
		||||
Framework.GetItemCount = function(item)
 | 
			
		||||
    local inventory = Framework.GetPlayerInventory()
 | 
			
		||||
    if not inventory then return 0 end
 | 
			
		||||
    return inventory[item].count or 0
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return a table of the players inventory
 | 
			
		||||
---@return table
 | 
			
		||||
Framework.GetPlayerInventory = function()
 | 
			
		||||
    local playerData = Framework.GetPlayerData()
 | 
			
		||||
    return playerData.inventory
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return the players money by type, I recommend not useing this as its the client and not secure or to be trusted.
 | 
			
		||||
---Use case is for a ui or a menu I guess.
 | 
			
		||||
---@param _type string
 | 
			
		||||
---@return number
 | 
			
		||||
Framework.GetAccountBalance = function(_type)
 | 
			
		||||
    local player = Framework.GetPlayerData()
 | 
			
		||||
    if not player then return 0 end
 | 
			
		||||
    local accounts = player.accounts
 | 
			
		||||
    if _type == 'cash' then _type = 'money' end
 | 
			
		||||
    for _, account in ipairs(accounts) do
 | 
			
		||||
        if account.name == _type then
 | 
			
		||||
            return account.money or 0
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
    return 0
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return the vehicle properties for the specified vehicle.
 | 
			
		||||
---@param vehicle number
 | 
			
		||||
---@return table
 | 
			
		||||
Framework.GetVehicleProperties = function(vehicle)
 | 
			
		||||
    if not vehicle or not DoesEntityExist(vehicle) then return {} end
 | 
			
		||||
    local vehicleProps = ESX.Game.GetVehicleProperties(vehicle)
 | 
			
		||||
    return vehicleProps or {}
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will set the vehicle properties for the specified vehicle.
 | 
			
		||||
---@param vehicle number
 | 
			
		||||
---@param properties table
 | 
			
		||||
---@return boolean
 | 
			
		||||
Framework.SetVehicleProperties = function(vehicle, properties)
 | 
			
		||||
    if not vehicle or not DoesEntityExist(vehicle) then return false end
 | 
			
		||||
    if not properties then return false end
 | 
			
		||||
    if NetworkGetEntityIsNetworked(vehicle) then
 | 
			
		||||
        local vehNetID = NetworkGetNetworkIdFromEntity(vehicle)
 | 
			
		||||
        local entOwner = GetPlayerServerId(NetworkGetEntityOwner(vehNetID))
 | 
			
		||||
        if entOwner ~= GetPlayerServerId(PlayerId()) then
 | 
			
		||||
            NetworkRequestControlOfEntity(vehicle)
 | 
			
		||||
            local count = 0
 | 
			
		||||
            while not NetworkHasControlOfEntity(vehicle) and count < 3000 do
 | 
			
		||||
                Wait(1)
 | 
			
		||||
                count = count + 1
 | 
			
		||||
            end
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
    -- Every framework version does this just a diffrent key I guess?
 | 
			
		||||
    if properties.color1 and type(properties.color1) == 'table' then
 | 
			
		||||
        properties.customPrimaryColor = {properties.color1[1], properties.color1[2], properties.color1[3]}
 | 
			
		||||
        properties.color1 = nil
 | 
			
		||||
    end
 | 
			
		||||
    if properties.color2 and type(properties.color2) == 'table' then
 | 
			
		||||
        properties.customSecondaryColor = {properties.color2[1], properties.color2[2], properties.color2[3]}
 | 
			
		||||
        properties.color2 = nil
 | 
			
		||||
    end
 | 
			
		||||
    return true, ESX.Game.SetVehicleProperties(vehicle, properties)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will get a players dead status.
 | 
			
		||||
---@return boolean
 | 
			
		||||
Framework.GetIsPlayerDead = function()
 | 
			
		||||
    local playerData = Framework.GetPlayerData()
 | 
			
		||||
    return playerData.dead
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
RegisterNetEvent('esx:playerLoaded', function(xPlayer)
 | 
			
		||||
    Wait(1500)
 | 
			
		||||
    TriggerEvent('community_bridge:Client:OnPlayerLoaded')
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
RegisterNetEvent('esx:onPlayerLogout', function()
 | 
			
		||||
    TriggerEvent('community_bridge:Client:OnPlayerUnload')
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
RegisterNetEvent('esx:setJob', function(data)
 | 
			
		||||
    TriggerEvent('community_bridge:Client:OnPlayerJobUpdate', data.name, data.label, data.grade_label, data.grade)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
return Framework
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,501 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
if GetResourceState('es_extended') ~= 'started' then return end
 | 
			
		||||
 | 
			
		||||
Prints = Prints or Require("lib/utility/shared/prints.lua")
 | 
			
		||||
Callback = Callback or Require("lib/utility/shared/callbacks.lua")
 | 
			
		||||
 | 
			
		||||
ESX = exports["es_extended"]:getSharedObject()
 | 
			
		||||
 | 
			
		||||
Framework = Framework or {}
 | 
			
		||||
 | 
			
		||||
local cachedItemList = nil
 | 
			
		||||
 | 
			
		||||
---This will return the name of the framework in use.
 | 
			
		||||
---@return string
 | 
			
		||||
Framework.GetFrameworkName = function()
 | 
			
		||||
    return 'es_extended'
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- This is an internal function, its here to attempt to emulate qbs shared items mainly.
 | 
			
		||||
Framework.ItemList = function()
 | 
			
		||||
    if cachedItemList then return cachedItemList end
 | 
			
		||||
    local items = ESX.Items
 | 
			
		||||
    local repackedTable = {}
 | 
			
		||||
    for k, v in pairs(items) do
 | 
			
		||||
        if v.label then
 | 
			
		||||
            repackedTable[k] = {
 | 
			
		||||
                name = k,
 | 
			
		||||
                label = v.label,
 | 
			
		||||
                weight = v.weight,
 | 
			
		||||
                type = "item",
 | 
			
		||||
                image = k .. ".png",
 | 
			
		||||
                unique = false,
 | 
			
		||||
                useable = true,
 | 
			
		||||
                shouldClose = true,
 | 
			
		||||
                description = 'No description provided.',
 | 
			
		||||
            }
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
    cachedItemList = { Items = repackedTable or {} }
 | 
			
		||||
    return cachedItemList
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return if the player is an admin in the framework.
 | 
			
		||||
---@param src any
 | 
			
		||||
---@return boolean
 | 
			
		||||
Framework.GetIsFrameworkAdmin = function(src)
 | 
			
		||||
    if not src then return false end
 | 
			
		||||
    local xPlayer = Framework.GetPlayer(src)
 | 
			
		||||
    if not xPlayer then return false end
 | 
			
		||||
    local group = xPlayer.getGroup()
 | 
			
		||||
    if group == 'admin' or group == 'superadmin' then return true end
 | 
			
		||||
    return false
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will get the players birth date
 | 
			
		||||
---@return string|nil
 | 
			
		||||
Framework.GetPlayerDob = function(src)
 | 
			
		||||
    local xPlayer = Framework.GetPlayer(src)
 | 
			
		||||
    if not xPlayer then return end
 | 
			
		||||
    local dob = xPlayer.get("dateofbirth")
 | 
			
		||||
    return dob
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
--- Returns the player data of the specified source in the framework defualt format.
 | 
			
		||||
---@param src any
 | 
			
		||||
---@return table | nil
 | 
			
		||||
Framework.GetPlayer = function(src)
 | 
			
		||||
    local xPlayer = ESX.GetPlayerFromId(src)
 | 
			
		||||
    if not xPlayer then return end
 | 
			
		||||
    return xPlayer
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Framework.GetPlayerIdentifier(src)
 | 
			
		||||
-- Returns the citizen ID of the player.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@return string | nil
 | 
			
		||||
Framework.GetPlayerIdentifier = function(src)
 | 
			
		||||
    local xPlayer = Framework.GetPlayer(src)
 | 
			
		||||
    if not xPlayer then return end
 | 
			
		||||
    return xPlayer.getIdentifier()
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return the jobs registered in the framework in a table.
 | 
			
		||||
---Format of the table is:
 | 
			
		||||
---{name = jobName, label = jobLabel, grade = {name = gradeName, level = gradeLevel}}
 | 
			
		||||
---@return table
 | 
			
		||||
Framework.GetFrameworkJobs = function()
 | 
			
		||||
    return ESX.GetJobs()
 | 
			
		||||
end
 | 
			
		||||
-- Framework.GetPlayerName(src)
 | 
			
		||||
-- Returns the first and last name of the player.
 | 
			
		||||
---@return string|nil, string|nil
 | 
			
		||||
Framework.GetPlayerName = function(src)
 | 
			
		||||
    local xPlayer = Framework.GetPlayer(src)
 | 
			
		||||
    if not xPlayer then return end
 | 
			
		||||
    return xPlayer.variables.firstName, xPlayer.variables.lastName
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return a table of all logged in players
 | 
			
		||||
---@return table
 | 
			
		||||
Framework.GetPlayers = function()
 | 
			
		||||
    local players = ESX.GetExtendedPlayers()
 | 
			
		||||
    local playerList = {}
 | 
			
		||||
    for _, xPlayer in pairs(players) do
 | 
			
		||||
        table.insert(playerList, xPlayer.source)
 | 
			
		||||
    end
 | 
			
		||||
    return playerList
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Returns a table of items matching the specified name and if passed metadata from the player's inventory.
 | 
			
		||||
---returns {name = v.name, count = v.amount, metadata = v.info, slot = v.slot}
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param item string
 | 
			
		||||
---@param _ table
 | 
			
		||||
---@return table|nil
 | 
			
		||||
Framework.GetItem = function(src, item, _)
 | 
			
		||||
    local xPlayer = Framework.GetPlayer(src)
 | 
			
		||||
    if not xPlayer then return end
 | 
			
		||||
    local playerItems = xPlayer.getInventory()
 | 
			
		||||
    local repackedTable = {}
 | 
			
		||||
    for _, v in pairs(playerItems) do
 | 
			
		||||
        if v.name == item then
 | 
			
		||||
            table.insert(repackedTable, {
 | 
			
		||||
                name = v.name,
 | 
			
		||||
                count = v.count,
 | 
			
		||||
                --metadata = v.metadata,
 | 
			
		||||
                --slot = v.slot,
 | 
			
		||||
            })
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
    return repackedTable
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return the count of the item in the players inventory, if not found will return 0.
 | 
			
		||||
---if metadata is passed it will find the matching items count (esx_core does not feature metadata items).
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param item string
 | 
			
		||||
---@param _ table
 | 
			
		||||
---@return number
 | 
			
		||||
Framework.GetItemCount = function(src, item, _)
 | 
			
		||||
    local xPlayer = Framework.GetPlayer(src)
 | 
			
		||||
    if not xPlayer then return end
 | 
			
		||||
    return xPlayer.getInventoryItem(item).count
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return a boolean if the player has the item.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param item string
 | 
			
		||||
---@return boolean
 | 
			
		||||
Framework.HasItem = function(src, item)
 | 
			
		||||
    local getCount = Framework.GetItemCount(src, item, nil)
 | 
			
		||||
    return getCount > 0
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Framework.GetPlayerInventory(src)
 | 
			
		||||
-- Returns the entire inventory of the player as a table.
 | 
			
		||||
-- returns {name = v.name, count = v.amount, metadata = v.info, slot = v.slot}
 | 
			
		||||
---@param src number
 | 
			
		||||
---@return table | nil
 | 
			
		||||
Framework.GetPlayerInventory = function(src)
 | 
			
		||||
    local xPlayer = Framework.GetPlayer(src)
 | 
			
		||||
    if not xPlayer then return end
 | 
			
		||||
    local playerItems = xPlayer.getInventory()
 | 
			
		||||
    local repackedTable = {}
 | 
			
		||||
    for _, v in pairs(playerItems) do
 | 
			
		||||
        if v.count > 0 then
 | 
			
		||||
            table.insert(repackedTable, {
 | 
			
		||||
                name = v.name,
 | 
			
		||||
                count = v.count,
 | 
			
		||||
                --metadata = v.metadata,
 | 
			
		||||
                --slot = v.slot,
 | 
			
		||||
            })
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
    return repackedTable
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Framework.SetMetadata(src, metadata, value)
 | 
			
		||||
-- Adds the specified metadata key and number value to the player's data.
 | 
			
		||||
---@return boolean|nil
 | 
			
		||||
Framework.SetPlayerMetadata = function(src, metadata, value)
 | 
			
		||||
    local xPlayer = Framework.GetPlayer(src)
 | 
			
		||||
    if not xPlayer then return end
 | 
			
		||||
    xPlayer.setMeta(metadata, value, nil)
 | 
			
		||||
    return true
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Framework.GetMetadata(src, metadata)
 | 
			
		||||
-- Gets the specified metadata key to the player's data.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param metadata string
 | 
			
		||||
---@return any|nil
 | 
			
		||||
Framework.GetPlayerMetadata = function(src, metadata)
 | 
			
		||||
    local xPlayer = Framework.GetPlayer(src)
 | 
			
		||||
    if not xPlayer then return end
 | 
			
		||||
    return xPlayer.getMeta(metadata) or false
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- defualt esx Available tables are
 | 
			
		||||
-- identifier, accounts, group, inventory, job, job_grade, loadout,
 | 
			
		||||
-- metadata, position, firstname, lastname, dateofbirth, sex, height,
 | 
			
		||||
-- skin, status, is_dead, id, disabled, last_property, created_at, last_seen,
 | 
			
		||||
-- phone_number, pincode
 | 
			
		||||
Framework.GetStatus = function(src, column)
 | 
			
		||||
    local xPlayer = Framework.GetPlayer(src)
 | 
			
		||||
    if not xPlayer then return end
 | 
			
		||||
    return xPlayer.get(column) or nil
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return a boolean if the player is dead or in last stand.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@return boolean|nil
 | 
			
		||||
Framework.GetIsPlayerDead = function(src)
 | 
			
		||||
    local xPlayer = Framework.GetPlayer(src)
 | 
			
		||||
    if not xPlayer then return end
 | 
			
		||||
    return xPlayer.get("is_dead") or false
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will revive a player, if the player is dead or in last stand.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@return boolean
 | 
			
		||||
Framework.RevivePlayer = function(src)
 | 
			
		||||
    src = tonumber(src)
 | 
			
		||||
    if not src then return false end
 | 
			
		||||
    TriggerEvent('esx_ambulancejob:revive', src)
 | 
			
		||||
    return true
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Framework.AddThirst(src, value)
 | 
			
		||||
-- Adds the specified value from the player's thirst level.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param value number
 | 
			
		||||
---@return number | nil
 | 
			
		||||
Framework.AddThirst = function(src, value)
 | 
			
		||||
    local clampIT = Math.Clamp(value, 0, 200000)
 | 
			
		||||
    local levelForEsx = clampIT * 2000
 | 
			
		||||
    TriggerClientEvent('esx_status:add', src, 'thirst', levelForEsx)
 | 
			
		||||
    return levelForEsx
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Framework.AddHunger(src, value)
 | 
			
		||||
-- Adds the specified value from the player's hunger level.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param value number
 | 
			
		||||
---@return number | nil
 | 
			
		||||
Framework.AddHunger = function(src, value)
 | 
			
		||||
    local clampIT = Math.Clamp(value, 0, 200000)
 | 
			
		||||
    local levelForEsx = clampIT * 2000
 | 
			
		||||
    TriggerClientEvent('esx_status:add', src, 'hunger', levelForEsx)
 | 
			
		||||
    return levelForEsx
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will get the hunger of a player
 | 
			
		||||
---@param src number
 | 
			
		||||
---@return number | nil
 | 
			
		||||
Framework.GetHunger = function(src)
 | 
			
		||||
    local status = Framework.GetStatus(src, "status")
 | 
			
		||||
    if not status then return 0 end
 | 
			
		||||
    return status.hunger
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will get the thirst of a player
 | 
			
		||||
---@param src any
 | 
			
		||||
---@return number | nil
 | 
			
		||||
Framework.GetThirst = function(src)
 | 
			
		||||
    local status = Framework.GetStatus(src, "status")
 | 
			
		||||
    if not status then return 0 end
 | 
			
		||||
    return status.thirst
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Framework.GetPlayerPhone(src)
 | 
			
		||||
-- Returns the phone number of the player.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@return string | nil
 | 
			
		||||
Framework.GetPlayerPhone = function(src)
 | 
			
		||||
    local xPlayer = Framework.GetPlayer(src)
 | 
			
		||||
    if not xPlayer then return end
 | 
			
		||||
    return xPlayer.get("phone_number")
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
---Depricated: Returns the job name, label, grade name, and grade level of the player.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@return string | nil
 | 
			
		||||
---@return string | nil
 | 
			
		||||
---@return string | nil
 | 
			
		||||
---@return string | nil
 | 
			
		||||
Framework.GetPlayerJob = function(src)
 | 
			
		||||
    local xPlayer = Framework.GetPlayer(src)
 | 
			
		||||
    if not xPlayer then return end
 | 
			
		||||
    local job = xPlayer.getJob()
 | 
			
		||||
    return job.name, job.label, job.grade_label, job.grade
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return the players job name, job label, job grade label job grade level, boss status, and duty status in a table
 | 
			
		||||
---@param src number
 | 
			
		||||
---@return table | nil
 | 
			
		||||
Framework.GetPlayerJobData = function(src)
 | 
			
		||||
    local xPlayer = Framework.GetPlayer(src)
 | 
			
		||||
    if not xPlayer then return end
 | 
			
		||||
    local job = xPlayer.getJob()
 | 
			
		||||
    local isBoss = (job.grade_name == "boss")
 | 
			
		||||
    return {
 | 
			
		||||
        jobName = job.name,
 | 
			
		||||
        jobLabel = job.label,
 | 
			
		||||
        gradeName = job.grade_name,
 | 
			
		||||
        gradeLabel = job.grade_label,
 | 
			
		||||
        gradeRank = job.grade,
 | 
			
		||||
        boss = isBoss,
 | 
			
		||||
        onDuty = job.onduty,
 | 
			
		||||
    }
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Returns the players duty status.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@return boolean
 | 
			
		||||
Framework.GetPlayerDuty = function(src)
 | 
			
		||||
    local xPlayer = Framework.GetPlayer(src)
 | 
			
		||||
    if not xPlayer then return false end
 | 
			
		||||
    local job = xPlayer.getJob()
 | 
			
		||||
    if not job.onDuty then return false end
 | 
			
		||||
    return true
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will toggle a players duty status
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param status boolean
 | 
			
		||||
---@return boolean
 | 
			
		||||
Framework.SetPlayerDuty = function(src, status)
 | 
			
		||||
    local xPlayer = Framework.GetPlayer(src)
 | 
			
		||||
    if not xPlayer then return false end
 | 
			
		||||
    local job = xPlayer.getJob()
 | 
			
		||||
    if not job.onDuty then return false end
 | 
			
		||||
    xPlayer.setJob(job.name, job.grade, status)
 | 
			
		||||
    return true
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will get a table of player sources that have the specified job name.
 | 
			
		||||
---@param job any
 | 
			
		||||
---@return table
 | 
			
		||||
Framework.GetPlayersByJob = function(job)
 | 
			
		||||
    local players = GetPlayers()
 | 
			
		||||
    local playerList = {}
 | 
			
		||||
    for _, src in pairs(players) do
 | 
			
		||||
        local xPlayer = Framework.GetPlayer(src)
 | 
			
		||||
        if xPlayer and xPlayer.getJob().name == job then
 | 
			
		||||
            table.insert(playerList, src)
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
    return playerList
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Sets the player's job to the specified name and grade.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param name string
 | 
			
		||||
---@param grade string
 | 
			
		||||
---@return nil
 | 
			
		||||
Framework.SetPlayerJob = function(src, name, grade)
 | 
			
		||||
    local xPlayer = Framework.GetPlayer(src)
 | 
			
		||||
    if not xPlayer then return end
 | 
			
		||||
    if not ESX.DoesJobExist(name, grade) then
 | 
			
		||||
        Prints.Error("Job Does Not Exsist In Framework :NAME " .. name .. " Grade:" .. grade)
 | 
			
		||||
        return
 | 
			
		||||
    end
 | 
			
		||||
    xPlayer.setJob(name, grade, true)
 | 
			
		||||
    return true 
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will add money based on the type of account (money/bank)
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param _type string
 | 
			
		||||
---@param amount number
 | 
			
		||||
---@return boolean | nil
 | 
			
		||||
Framework.AddAccountBalance = function(src, _type, amount)
 | 
			
		||||
    local xPlayer = Framework.GetPlayer(src)
 | 
			
		||||
    if not xPlayer then return end
 | 
			
		||||
    if _type == 'cash' then _type = 'money' end
 | 
			
		||||
    xPlayer.addAccountMoney(_type, amount)
 | 
			
		||||
    return true
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will remove money based on the type of account (money/bank)
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param _type string
 | 
			
		||||
---@param amount number
 | 
			
		||||
---@return boolean | nil
 | 
			
		||||
Framework.RemoveAccountBalance = function(src, _type, amount)
 | 
			
		||||
    local xPlayer = Framework.GetPlayer(src)
 | 
			
		||||
    if not xPlayer then return end
 | 
			
		||||
    if _type == 'cash' then _type = 'money' end
 | 
			
		||||
    xPlayer.removeAccountMoney(_type, amount)
 | 
			
		||||
    return true
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will remove money based on the type of account (money/bank)
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param _type string
 | 
			
		||||
---@return string | nil
 | 
			
		||||
Framework.GetAccountBalance = function(src, _type)
 | 
			
		||||
    local xPlayer = Framework.GetPlayer(src)
 | 
			
		||||
    if not xPlayer then return end
 | 
			
		||||
    if _type == 'cash' then _type = 'money' end
 | 
			
		||||
    return xPlayer.getAccount(_type).money
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Framework.AddItem(src, item, amount, slot, metadata)
 | 
			
		||||
-- Adds the specified item to the player's inventory.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param item string
 | 
			
		||||
---@param amount number
 | 
			
		||||
---@param slot number
 | 
			
		||||
---@param metadata table
 | 
			
		||||
---@return boolean | nil
 | 
			
		||||
Framework.AddItem = function(src, item, amount, slot, metadata)
 | 
			
		||||
    local xPlayer = Framework.GetPlayer(src)
 | 
			
		||||
    if not xPlayer then return end
 | 
			
		||||
    xPlayer.addInventoryItem(item, amount)
 | 
			
		||||
    return true
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Framework.RemoveItem(src, item, amount, slot, metadata)
 | 
			
		||||
-- Removes the specified item from the player's inventory.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param item string
 | 
			
		||||
---@param amount number
 | 
			
		||||
---@param slot number
 | 
			
		||||
---@param metadata table
 | 
			
		||||
---@return boolean | nil
 | 
			
		||||
Framework.RemoveItem = function(src, item, amount, slot, metadata)
 | 
			
		||||
    local xPlayer = Framework.GetPlayer(src)
 | 
			
		||||
    if not xPlayer then return end
 | 
			
		||||
    xPlayer.removeInventoryItem(item, amount)
 | 
			
		||||
    return true
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will get all owned vehicles for the player
 | 
			
		||||
---@param src number
 | 
			
		||||
---@return table
 | 
			
		||||
Framework.GetOwnedVehicles = function(src)
 | 
			
		||||
    local citizenId = Framework.GetPlayerIdentifier(src)
 | 
			
		||||
    local result = MySQL.Sync.fetchAll("SELECT vehicle, plate FROM owned_vehicles WHERE owner = '" .. citizenId .. "'")
 | 
			
		||||
    local vehicles = {}
 | 
			
		||||
    for i = 1, #result do
 | 
			
		||||
        local vehicle = result[i].vehicle
 | 
			
		||||
        local plate = result[i].plate
 | 
			
		||||
        local model = json.decode(vehicle).model
 | 
			
		||||
        table.insert(vehicles, { vehicle = model, plate = plate })
 | 
			
		||||
    end
 | 
			
		||||
    return vehicles
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
-- Framework.RegisterUsableItem(item, cb)
 | 
			
		||||
-- Registers a usable item with a callback function.
 | 
			
		||||
---@param itemName string
 | 
			
		||||
---@param cb function
 | 
			
		||||
Framework.RegisterUsableItem = function(itemName, cb)
 | 
			
		||||
    local func = function(src, item, itemData)
 | 
			
		||||
        itemData = itemData or item
 | 
			
		||||
        itemData.metadata = itemData.metadata or itemData.info or {}
 | 
			
		||||
        itemData.slot = itemData.id or itemData.slot
 | 
			
		||||
        cb(src, itemData)
 | 
			
		||||
    end
 | 
			
		||||
    ESX.RegisterUsableItem(itemName, func)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
RegisterNetEvent("esx:playerLoaded", function(src)
 | 
			
		||||
    src = src or source
 | 
			
		||||
    TriggerEvent("community_bridge:Server:OnPlayerLoaded", src)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
RegisterNetEvent("esx:playerLogout", function(src)
 | 
			
		||||
    src = src or source
 | 
			
		||||
    TriggerEvent("community_bridge:Server:OnPlayerUnload", src)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
AddEventHandler("playerDropped", function()
 | 
			
		||||
    local src = source
 | 
			
		||||
    TriggerEvent("community_bridge:Server:OnPlayerUnload", src)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
Callback.Register('community_bridge:Callback:GetFrameworkJobs', function(source)
 | 
			
		||||
    return Framework.GetFrameworkJobs() or {}
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
-- This is linked to an internal function, its an attempt to standardize the item list across frameworks.
 | 
			
		||||
Callback.Register('community_bridge:Callback:GetFrameworkItems', function(source)
 | 
			
		||||
    return Framework.ItemList() or {}
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
Framework.Commands = {}
 | 
			
		||||
Framework.Commands.Add = function(name, help, arguments, argsrequired, callback, permission, ...)
 | 
			
		||||
    ESX.RegisterCommand(name, permission, function(xPlayer, args, showError)
 | 
			
		||||
        callback(xPlayer, args)
 | 
			
		||||
    end, false, {
 | 
			
		||||
        help = help,
 | 
			
		||||
        arguments = arguments
 | 
			
		||||
    })
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return Framework
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,255 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
if GetResourceState('qb-core') ~= 'started' then return end
 | 
			
		||||
if GetResourceState('qbx_core') == 'started' then return end
 | 
			
		||||
 | 
			
		||||
Framework = Framework or {}
 | 
			
		||||
 | 
			
		||||
QBCore = exports['qb-core']:GetCoreObject()
 | 
			
		||||
 | 
			
		||||
Framework.Shared = QBCore.Shared
 | 
			
		||||
 | 
			
		||||
---This will get the name of the framework being used (if a supported framework).
 | 
			
		||||
---@return string
 | 
			
		||||
Framework.GetFrameworkName = function()
 | 
			
		||||
    return 'qb-core'
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return true if the player is loaded, false otherwise.
 | 
			
		||||
---This could be useful in scripts that rely on player loaded events and offer a debug mode to hit this function.
 | 
			
		||||
---@return boolean
 | 
			
		||||
Framework.GetIsPlayerLoaded = function()
 | 
			
		||||
    return LocalPlayer.state.isLoggedIn or false
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return a table of the player data, this will be in the framework format.
 | 
			
		||||
---This is mainly for internal bridge use and should be avoided.
 | 
			
		||||
---@return table
 | 
			
		||||
Framework.GetPlayerData = function()
 | 
			
		||||
    return QBCore.Functions.GetPlayerData()
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return a table of all the jobs in the framework.
 | 
			
		||||
---@return table
 | 
			
		||||
Framework.GetFrameworkJobs = function()
 | 
			
		||||
    local jobs = {}
 | 
			
		||||
    for k, v in pairs(QBCore.Shared.Jobs) do
 | 
			
		||||
        table.insert(jobs, {
 | 
			
		||||
            name = k,
 | 
			
		||||
            label = v.label,
 | 
			
		||||
            grade = v.grades
 | 
			
		||||
        })
 | 
			
		||||
    end
 | 
			
		||||
    return jobs
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will get the players birth date
 | 
			
		||||
---@return string
 | 
			
		||||
Framework.GetPlayerDob = function()
 | 
			
		||||
    local player = Framework.GetPlayerData()
 | 
			
		||||
    local playerData = player.PlayerData
 | 
			
		||||
    return playerData.charinfo.birthdate
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return the players metadata for the specified metadata key.
 | 
			
		||||
---@param metadata table | string
 | 
			
		||||
---@return table | string | number | boolean
 | 
			
		||||
Framework.GetPlayerMetaData = function(metadata)
 | 
			
		||||
    return Framework.GetPlayerData().metadata[metadata]
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will send a notification to the player.
 | 
			
		||||
---@param message string
 | 
			
		||||
---@param type string
 | 
			
		||||
---@param time number
 | 
			
		||||
---@return nil
 | 
			
		||||
Framework.Notify = function(message, type, time)
 | 
			
		||||
    TriggerEvent('QBCore:Notify', message, 'primary', time)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Will Display the help text message on the screen
 | 
			
		||||
---@param message string
 | 
			
		||||
---@param _position unknown
 | 
			
		||||
---@return nil
 | 
			
		||||
Framework.ShowHelpText = function(message, _position)
 | 
			
		||||
    return exports['qb-core']:DrawText(message, _position)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will hide the help text message on the screen
 | 
			
		||||
---@return nil
 | 
			
		||||
Framework.HideHelpText = function()
 | 
			
		||||
    return exports['qb-core']:HideText()
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return the players money by type, I recommend not useing this as its the client and not secure or to be trusted.
 | 
			
		||||
---Use case is for a ui or a menu I guess.
 | 
			
		||||
---@param _type string
 | 
			
		||||
---@return number
 | 
			
		||||
Framework.GetAccountBalance = function(_type)
 | 
			
		||||
    local player = Framework.GetPlayerData()
 | 
			
		||||
    if not player then return 0 end
 | 
			
		||||
    local account = player.money
 | 
			
		||||
    if _type == 'money' then _type = 'cash' end
 | 
			
		||||
    return account[_type] or 0
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return the item data for the specified item.
 | 
			
		||||
---@param item string
 | 
			
		||||
---@return table
 | 
			
		||||
Framework.GetItemInfo = function(item)
 | 
			
		||||
    local itemData = QBCore.Shared.Items[item]
 | 
			
		||||
    if not itemData then return {} end
 | 
			
		||||
    local repackedTable = {
 | 
			
		||||
        name = itemData.name,
 | 
			
		||||
        label = itemData.label,
 | 
			
		||||
        stack = itemData.unique,
 | 
			
		||||
        weight = itemData.weight,
 | 
			
		||||
        description = itemData.description,
 | 
			
		||||
        image = itemData.image
 | 
			
		||||
    }
 | 
			
		||||
    return repackedTable
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will get the players identifier (citizenid) etc.
 | 
			
		||||
---@return string
 | 
			
		||||
Framework.GetPlayerIdentifier = function()
 | 
			
		||||
    return Framework.GetPlayerData().citizenid
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will get the players name (first and last).
 | 
			
		||||
---@return string
 | 
			
		||||
---@return string
 | 
			
		||||
Framework.GetPlayerName = function()
 | 
			
		||||
    local playerData = Framework.GetPlayerData()
 | 
			
		||||
    return playerData.charinfo.firstname, playerData.charinfo.lastname
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Depricated : This will return the players job name, job label, job grade label and job grade level
 | 
			
		||||
---@return string
 | 
			
		||||
---@return string
 | 
			
		||||
---@return string
 | 
			
		||||
---@return string
 | 
			
		||||
Framework.GetPlayerJob = function()
 | 
			
		||||
    local playerData = Framework.GetPlayerData()
 | 
			
		||||
    return playerData.job.name, playerData.job.label, playerData.job.grade.name, playerData.job.grade.level
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return the players job name, job label, job grade label job grade level, boss status, and duty status in a table
 | 
			
		||||
---@return table
 | 
			
		||||
Framework.GetPlayerJobData = function()
 | 
			
		||||
    local playerData = Framework.GetPlayerData()
 | 
			
		||||
    local jobData = playerData.job
 | 
			
		||||
    return {
 | 
			
		||||
        jobName = jobData.name,
 | 
			
		||||
        jobLabel = jobData.label,
 | 
			
		||||
        gradeName = jobData.grade.name,
 | 
			
		||||
        gradeLabel = jobData.grade.name,
 | 
			
		||||
        gradeRank = jobData.grade.level,
 | 
			
		||||
        boss = jobData.isboss,
 | 
			
		||||
        onDuty = jobData.onduty,
 | 
			
		||||
    }
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return if the player has the specified item in their inventory.
 | 
			
		||||
---@param item string
 | 
			
		||||
---@return boolean
 | 
			
		||||
Framework.HasItem = function(item)
 | 
			
		||||
	return QBCore.Functions.HasItem(item)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return the item count for the specified item in the players inventory.
 | 
			
		||||
---@param item string
 | 
			
		||||
---@return number
 | 
			
		||||
Framework.GetItemCount = function(item)
 | 
			
		||||
    local frameworkInv = Framework.GetPlayerData().items
 | 
			
		||||
    local count = 0
 | 
			
		||||
    for _, v in pairs(frameworkInv) do
 | 
			
		||||
        if v.name == item then
 | 
			
		||||
            count = count + v.amount
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
    return count
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return the players inventory as a table in the ox_inventory style flormat.
 | 
			
		||||
---@return table
 | 
			
		||||
Framework.GetPlayerInventory = function()
 | 
			
		||||
    local items = {}
 | 
			
		||||
    local frameworkInv = Framework.GetPlayerData().items
 | 
			
		||||
    for _, v in pairs(frameworkInv) do
 | 
			
		||||
        table.insert(items, {
 | 
			
		||||
            name = v.name,
 | 
			
		||||
            label = v.label,
 | 
			
		||||
            count = v.amount,
 | 
			
		||||
            slot = v.slot,
 | 
			
		||||
            metadata = v.info,
 | 
			
		||||
            stack = v.unique,
 | 
			
		||||
            close = v.useable,
 | 
			
		||||
            weight = v.weight
 | 
			
		||||
        })
 | 
			
		||||
    end
 | 
			
		||||
    return items
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return the vehicle properties for the specified vehicle.
 | 
			
		||||
---@param vehicle number
 | 
			
		||||
---@return table
 | 
			
		||||
Framework.GetVehicleProperties = function(vehicle)
 | 
			
		||||
    if not vehicle or not DoesEntityExist(vehicle) then return {} end
 | 
			
		||||
    local vehicleProps = QBCore.Functions.GetVehicleProperties(vehicle)
 | 
			
		||||
    return vehicleProps or {}
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will set the vehicle properties for the specified vehicle.
 | 
			
		||||
---@param vehicle number
 | 
			
		||||
---@param properties table
 | 
			
		||||
---@return boolean
 | 
			
		||||
Framework.SetVehicleProperties = function(vehicle, properties)
 | 
			
		||||
    if not vehicle or not DoesEntityExist(vehicle) then return false end
 | 
			
		||||
    if not properties then return false end
 | 
			
		||||
    if NetworkGetEntityIsNetworked(vehicle) then
 | 
			
		||||
        local vehNetID = NetworkGetNetworkIdFromEntity(vehicle)
 | 
			
		||||
        local entOwner = GetPlayerServerId(NetworkGetEntityOwner(vehNetID))
 | 
			
		||||
        if entOwner ~= GetPlayerServerId(PlayerId()) then
 | 
			
		||||
            NetworkRequestControlOfEntity(vehicle)
 | 
			
		||||
            local count = 0
 | 
			
		||||
            while not NetworkHasControlOfEntity(vehicle) and count < 3000 do
 | 
			
		||||
                Wait(1)
 | 
			
		||||
                count = count + 1
 | 
			
		||||
            end
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
    return true, QBCore.Functions.SetVehicleProperties(vehicle, properties)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will get a players dead status.
 | 
			
		||||
---@return boolean
 | 
			
		||||
Framework.GetIsPlayerDead = function()
 | 
			
		||||
    local playerData = Framework.GetPlayerData()
 | 
			
		||||
    return playerData.metadata["isdead"] or playerData.metadata["inlaststand"]
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function()
 | 
			
		||||
    Wait(1500)
 | 
			
		||||
    TriggerEvent('community_bridge:Client:OnPlayerLoaded')
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
RegisterNetEvent('QBCore:Client:OnPlayerUnload', function()
 | 
			
		||||
    TriggerEvent('community_bridge:Client:OnPlayerUnload')
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
RegisterNetEvent('QBCore:Client:OnJobUpdate', function(data)
 | 
			
		||||
    TriggerEvent('community_bridge:Client:OnPlayerJobUpdate', data.name, data.label, data.grade_label, data.grade)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
RegisterNetEvent('QBCore:Client:OnGangUpdate', function(data)
 | 
			
		||||
    -- Unsure what data is passed in this, but considering the gang data isnt updating I doubt this was tested.
 | 
			
		||||
    --[[
 | 
			
		||||
    PlayerJobName = data.name
 | 
			
		||||
    PlayerJobLabel = data.label
 | 
			
		||||
    PlayerJobGradeName = data.grade.name
 | 
			
		||||
    PlayerJobGradeLevel = data.grade.level
 | 
			
		||||
    TriggerEvent('community_bridge:Client:OnPlayerGangUpdate', PlayerGangName, PlayerGangLabel, PlayerGangGradeName, PlayerGangGradeLevel)
 | 
			
		||||
    --]]
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
return Framework
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,585 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
if GetResourceState('qb-core') ~= 'started' then return end
 | 
			
		||||
if GetResourceState('qbx_core') == 'started' then return end
 | 
			
		||||
 | 
			
		||||
Framework = Framework or {}
 | 
			
		||||
 | 
			
		||||
QBCore = exports['qb-core']:GetCoreObject()
 | 
			
		||||
 | 
			
		||||
Framework.Shared = QBCore.Shared
 | 
			
		||||
 | 
			
		||||
---This will return the name of the framework in use.
 | 
			
		||||
---@return string
 | 
			
		||||
Framework.GetFrameworkName = function()
 | 
			
		||||
    return 'qb-core'
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return if the player is an admin in the framework.
 | 
			
		||||
---@param src any
 | 
			
		||||
---@return boolean
 | 
			
		||||
Framework.GetIsFrameworkAdmin = function(src)
 | 
			
		||||
    if not src then return false end
 | 
			
		||||
    return QBCore.Functions.HasPermission(src, 'admin')
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Framework.GetPlayerIdentifier(src)
 | 
			
		||||
-- Returns the citizen ID of the player.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@return string | nil
 | 
			
		||||
Framework.GetPlayerIdentifier = function(src)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    local playerData = player.PlayerData
 | 
			
		||||
    return playerData.citizenid
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
--- Returns the player data of the specified source in the framework defualt format.
 | 
			
		||||
---@param src any
 | 
			
		||||
---@return table | nil
 | 
			
		||||
Framework.GetPlayer = function(src)
 | 
			
		||||
    local player = QBCore.Functions.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    return player
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return the jobs registered in the framework in a table.
 | 
			
		||||
---Format of the table is:
 | 
			
		||||
---{name = jobName, label = jobLabel, grade = {name = gradeName, level = gradeLevel}}
 | 
			
		||||
---@return table
 | 
			
		||||
Framework.GetFrameworkJobs = function()
 | 
			
		||||
    local jobs = {}
 | 
			
		||||
    for k, v in pairs(QBCore.Shared.Jobs) do
 | 
			
		||||
        table.insert(jobs, {
 | 
			
		||||
            name = k,
 | 
			
		||||
            label = v.label,
 | 
			
		||||
            grade = v.grades
 | 
			
		||||
        })
 | 
			
		||||
    end
 | 
			
		||||
    return jobs
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Framework.GetPlayerName(src)
 | 
			
		||||
-- Returns the first and last name of the player.
 | 
			
		||||
---@return string|nil, string|nil
 | 
			
		||||
Framework.GetPlayerName = function(src)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    local playerData = player.PlayerData
 | 
			
		||||
    return playerData.charinfo.firstname, playerData.charinfo.lastname
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Returns the player date of birth.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@return string|nil
 | 
			
		||||
Framework.GetPlayerDob = function(src)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    local playerData = player.PlayerData
 | 
			
		||||
    return playerData.charinfo.birthdate
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Returns a table of items matching the specified name and if passed metadata from the player's inventory.
 | 
			
		||||
---returns {name = v.name, count = v.amount, metadata = v.info, slot = v.slot}
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param item string
 | 
			
		||||
---@param metadata table
 | 
			
		||||
---@return table|nil
 | 
			
		||||
Framework.GetItem = function(src, item, metadata)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    local playerData = player.PlayerData
 | 
			
		||||
    local playerInventory = playerData.items
 | 
			
		||||
    local repackedTable = {}
 | 
			
		||||
    for _, v in pairs(playerInventory) do
 | 
			
		||||
        if v.name == item and (not metadata or v.info == metadata) then
 | 
			
		||||
            table.insert(repackedTable, {
 | 
			
		||||
                name = v.name,
 | 
			
		||||
                count = v.amount,
 | 
			
		||||
                metadata = v.info,
 | 
			
		||||
                slot = v.slot,
 | 
			
		||||
            })
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
    return repackedTable
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return a table with the item info, {name, label, stack, weight, description, image}
 | 
			
		||||
---@param item string
 | 
			
		||||
---@return table
 | 
			
		||||
Framework.GetItemInfo = function(item)
 | 
			
		||||
    local itemData = QBCore.Shared.Items[item]
 | 
			
		||||
    if not itemData then return {} end
 | 
			
		||||
    local repackedTable = {
 | 
			
		||||
        name = itemData.name,
 | 
			
		||||
        label = itemData.label,
 | 
			
		||||
        stack = itemData.unique,
 | 
			
		||||
        weight = itemData.weight,
 | 
			
		||||
        description = itemData.description,
 | 
			
		||||
        image = itemData.image
 | 
			
		||||
    }
 | 
			
		||||
    return repackedTable
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return the count of the item in the players inventory, if not found will return 0.
 | 
			
		||||
---
 | 
			
		||||
---if metadata is passed it will find the matching items count.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param item string
 | 
			
		||||
---@param metadata table
 | 
			
		||||
---@return number
 | 
			
		||||
Framework.GetItemCount = function(src, item, metadata)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return 0 end
 | 
			
		||||
    local playerData = player.PlayerData
 | 
			
		||||
    local playerInventory = playerData.items
 | 
			
		||||
    local count = 0
 | 
			
		||||
    for _, v in pairs(playerInventory) do
 | 
			
		||||
        if v.name == item and (not metadata or v.info == metadata) then
 | 
			
		||||
            count = count + v.amount
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
    return count
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return a boolean if the player has the item.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param item string
 | 
			
		||||
---@return boolean
 | 
			
		||||
Framework.HasItem = function(src, item)
 | 
			
		||||
    local getCount = Framework.GetItemCount(src, item, nil)
 | 
			
		||||
    return getCount > 0
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Framework.GetPlayerInventory(src)
 | 
			
		||||
-- Returns the entire inventory of the player as a table.
 | 
			
		||||
-- returns {name = v.name, count = v.amount, metadata = v.info, slot = v.slot}
 | 
			
		||||
---@param src number
 | 
			
		||||
---@return table | nil
 | 
			
		||||
Framework.GetPlayerInventory = function(src)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    local playerData = player.PlayerData
 | 
			
		||||
    local playerInventory = playerData.items
 | 
			
		||||
    local repackedTable = {}
 | 
			
		||||
    for _, v in pairs(playerInventory) do
 | 
			
		||||
        table.insert(repackedTable, {
 | 
			
		||||
            name = v.name,
 | 
			
		||||
            count = v.amount,
 | 
			
		||||
            metadata = v.info,
 | 
			
		||||
            slot = v.slot,
 | 
			
		||||
        })
 | 
			
		||||
    end
 | 
			
		||||
    return repackedTable
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return a table of all logged in players
 | 
			
		||||
---@return table
 | 
			
		||||
Framework.GetPlayers = function()
 | 
			
		||||
    local players = QBCore.Functions.GetPlayers()
 | 
			
		||||
    local playerList = {}
 | 
			
		||||
    for _, src in pairs(players) do
 | 
			
		||||
        table.insert(playerList, src)
 | 
			
		||||
    end
 | 
			
		||||
    return playerList
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return the item data for the specified slot.
 | 
			
		||||
---Format {name, label, weight, count, metadata, slot, stack, description}
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param slot number
 | 
			
		||||
---@return table|nil
 | 
			
		||||
Framework.GetItemBySlot = function(src, slot)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    local playerData = player.PlayerData
 | 
			
		||||
    local playerInventory = playerData.items
 | 
			
		||||
    local repack = {}
 | 
			
		||||
    for _, v in pairs(playerInventory) do
 | 
			
		||||
        if v.slot == slot then
 | 
			
		||||
            return {
 | 
			
		||||
                name = v.name,
 | 
			
		||||
                label = v.label,
 | 
			
		||||
                weight = v.weight,
 | 
			
		||||
                count = v.amount,
 | 
			
		||||
                metadata = v.info,
 | 
			
		||||
                slot = v.slot,
 | 
			
		||||
                stack = v.unique or false,
 | 
			
		||||
                description = v.description or "none",
 | 
			
		||||
            }
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
    return repack
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Framework.SetMetadata(src, metadata, value)
 | 
			
		||||
-- Adds the specified metadata key and number value to the player's data.
 | 
			
		||||
---@return boolean|nil
 | 
			
		||||
Framework.SetPlayerMetadata = function(src, metadata, value)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    player.Functions.SetMetaData(metadata, value)
 | 
			
		||||
    return true
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Framework.GetMetadata(src, metadata)
 | 
			
		||||
-- Gets the specified metadata key to the player's data.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param metadata string
 | 
			
		||||
---@return any|nil
 | 
			
		||||
Framework.GetPlayerMetadata = function(src, metadata)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    local playerData = player.PlayerData
 | 
			
		||||
    return playerData.metadata[metadata] or false
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Framework.AddStress(src, value)
 | 
			
		||||
-- Adds the specified value to the player's stress level and updates the client HUD.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param value number
 | 
			
		||||
---@return number | nil
 | 
			
		||||
Framework.AddStress = function(src, value)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    local playerData = player.PlayerData
 | 
			
		||||
    local newStress = playerData.metadata.stress + value
 | 
			
		||||
    player.Functions.SetMetaData('stress', Math.Clamp(newStress, 0, 100))
 | 
			
		||||
    TriggerClientEvent('hud:client:UpdateStress', src, newStress)
 | 
			
		||||
    return newStress
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Framework.RemoveStress(src, value)
 | 
			
		||||
-- Removes the specified value from the player's stress level and updates the client HUD.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param value number
 | 
			
		||||
---@return number | nil
 | 
			
		||||
Framework.RemoveStress = function(src, value)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    local playerData = player.PlayerData
 | 
			
		||||
    local newStress = (playerData.metadata.stress or 0) - value
 | 
			
		||||
    player.Functions.SetMetaData('stress', Math.Clamp(newStress, 0, 100))
 | 
			
		||||
    TriggerClientEvent('hud:client:UpdateStress', src, newStress)
 | 
			
		||||
    return newStress
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Framework.AddHunger(src, value)
 | 
			
		||||
-- Adds the specified value from the player's hunger level.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param value number
 | 
			
		||||
---@return number | nil
 | 
			
		||||
Framework.AddHunger = function(src, value)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    local playerData = player.PlayerData
 | 
			
		||||
    local newHunger = (playerData.metadata.hunger or 0) + value
 | 
			
		||||
    player.Functions.SetMetaData('hunger', Math.Clamp(newHunger, 0, 100))
 | 
			
		||||
    TriggerClientEvent('hud:client:UpdateNeeds', src, newHunger, playerData.metadata.thirst)
 | 
			
		||||
    --TriggerClientEvent('hud:client:UpdateStress', src, newStress)
 | 
			
		||||
    return newHunger
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Framework.AddThirst(src, value)
 | 
			
		||||
-- Adds the specified value from the player's thirst level.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param value number
 | 
			
		||||
---@return number | nil
 | 
			
		||||
Framework.AddThirst = function(src, value)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    local playerData = player.PlayerData
 | 
			
		||||
    local newThirst = (playerData.metadata.thirst or 0) + value
 | 
			
		||||
    player.Functions.SetMetaData('thirst', Math.Clamp(newThirst, 0, 100))
 | 
			
		||||
    TriggerClientEvent('hud:client:UpdateNeeds', src, playerData.metadata.hunger, newThirst)
 | 
			
		||||
    --TriggerClientEvent('hud:client:UpdateStress', src, newStress)
 | 
			
		||||
    return newThirst
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will get the hunger of a player
 | 
			
		||||
---@param src number
 | 
			
		||||
---@return number | nil
 | 
			
		||||
Framework.GetHunger = function(src)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    local playerData = player.PlayerData
 | 
			
		||||
    local newHunger = (playerData.metadata.hunger or 0)
 | 
			
		||||
    return newHunger
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return a boolean if the player is dead or in last stand.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@return boolean|nil
 | 
			
		||||
Framework.GetIsPlayerDead = function(src)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    local playerData = player.PlayerData
 | 
			
		||||
    return playerData.metadata.isdead or playerData.metadata.inlaststand or false
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will revive a player, if the player is dead or in last stand.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@return boolean
 | 
			
		||||
Framework.RevivePlayer = function(src)
 | 
			
		||||
    src = tonumber(src)
 | 
			
		||||
    if not src then return false end
 | 
			
		||||
    TriggerClientEvent('hospital:client:Revive', src)
 | 
			
		||||
    return true
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
---This will get the thirst of a player
 | 
			
		||||
---@param src any
 | 
			
		||||
---@return number | nil
 | 
			
		||||
Framework.GetThirst = function(src)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    local playerData = player.PlayerData
 | 
			
		||||
    local newThirst = (playerData.metadata.thirst or 0)
 | 
			
		||||
    return newThirst
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Framework.GetPlayerPhone(src)
 | 
			
		||||
-- Returns the phone number of the player.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@return string | nil
 | 
			
		||||
Framework.GetPlayerPhone = function(src)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    local playerData = player.PlayerData
 | 
			
		||||
    return playerData.charinfo.phone
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Framework.GetPlayerGang(src)
 | 
			
		||||
-- Returns the gang name of the player.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@return string | nil
 | 
			
		||||
Framework.GetPlayerGang = function(src)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    local playerData = player.PlayerData
 | 
			
		||||
    return playerData.gang.name
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will get a table of player sources that have the specified job name.
 | 
			
		||||
---@param job any
 | 
			
		||||
---@return table
 | 
			
		||||
Framework.GetPlayersByJob = function(job)
 | 
			
		||||
    local playerList = {}
 | 
			
		||||
    local players = QBCore.Functions.GetPlayers()
 | 
			
		||||
    for _, src in pairs(players) do
 | 
			
		||||
        local player = Framework.GetPlayer(src).PlayerData
 | 
			
		||||
        if player.job.name == job then
 | 
			
		||||
            table.insert(playerList, src)
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
    return playerList
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Depricated: Returns the job name, label, grade name, and grade level of the player.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@return string | string | string | number | nil
 | 
			
		||||
---@return string | string | string | number | nil
 | 
			
		||||
---@return string | string | string | number | nil
 | 
			
		||||
---@return string | string | string | number | nil
 | 
			
		||||
Framework.GetPlayerJob = function(src)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    local playerData = player.PlayerData
 | 
			
		||||
    return playerData.job.name, playerData.job.label, playerData.job.grade.name, playerData.job.grade.level
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return the players job name, job label, job grade label job grade level, boss status, and duty status in a table
 | 
			
		||||
---@param src number
 | 
			
		||||
---@return table | nil
 | 
			
		||||
Framework.GetPlayerJobData = function(src)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    local playerData = player.PlayerData
 | 
			
		||||
    local jobData = playerData.job
 | 
			
		||||
    return {
 | 
			
		||||
        jobName = jobData.name,
 | 
			
		||||
        jobLabel = jobData.label,
 | 
			
		||||
        gradeName = jobData.grade.name,
 | 
			
		||||
        gradeLabel = jobData.grade.name,
 | 
			
		||||
        gradeRank = jobData.grade.level,
 | 
			
		||||
        boss = jobData.isboss,
 | 
			
		||||
        onDuty = jobData.onduty,
 | 
			
		||||
    }
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Returns the players duty status.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@return boolean | nil
 | 
			
		||||
Framework.GetPlayerDuty = function(src)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    local playerData = player.PlayerData
 | 
			
		||||
    if not playerData.job.onduty then return false end
 | 
			
		||||
    return true
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will toggle a players duty status
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param status boolean
 | 
			
		||||
---@return boolean
 | 
			
		||||
Framework.SetPlayerDuty = function(src, status)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return false end
 | 
			
		||||
    player.Functions.SetJobDuty(status)
 | 
			
		||||
    TriggerEvent('QBCore:Server:SetDuty', src, player.PlayerData.job.onduty)
 | 
			
		||||
    return true
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Sets the player's job to the specified name and grade.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param name string
 | 
			
		||||
---@param grade string
 | 
			
		||||
---@return nil
 | 
			
		||||
Framework.SetPlayerJob = function(src, name, grade)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    return player.Functions.SetJob(name, grade)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will add money based on the type of account (money/bank)
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param _type string
 | 
			
		||||
---@param amount number
 | 
			
		||||
---@return boolean | nil
 | 
			
		||||
Framework.AddAccountBalance = function(src, _type, amount)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    if _type == 'money' then _type = 'cash' end
 | 
			
		||||
    return player.Functions.AddMoney(_type, amount)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will remove money based on the type of account (money/bank)
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param _type string
 | 
			
		||||
---@param amount number
 | 
			
		||||
---@return boolean | nil
 | 
			
		||||
Framework.RemoveAccountBalance = function(src, _type, amount)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    if _type == 'money' then _type = 'cash' end
 | 
			
		||||
    return player.Functions.RemoveMoney(_type, amount)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will remove money based on the type of account (money/bank)
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param _type string
 | 
			
		||||
---@return string | nil
 | 
			
		||||
Framework.GetAccountBalance = function(src, _type)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    local playerData = player.PlayerData
 | 
			
		||||
    if _type == 'money' then _type = 'cash' end
 | 
			
		||||
    return playerData.money[_type]
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Framework.AddItem(src, item, amount, slot, metadata)
 | 
			
		||||
-- Adds the specified item to the player's inventory.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param item string
 | 
			
		||||
---@param amount number
 | 
			
		||||
---@param slot number
 | 
			
		||||
---@param metadata table
 | 
			
		||||
---@return boolean | nil
 | 
			
		||||
Framework.AddItem = function(src, item, amount, slot, metadata)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    TriggerClientEvent("community_bridge:client:inventory:updateInventory", src, { action = "add", item = item, count = amount, slot = slot, metadata = metadata })
 | 
			
		||||
    return player.Functions.AddItem(item, amount, slot, metadata)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Framework.RemoveItem(src, item, amount, slot, metadata)
 | 
			
		||||
-- Removes the specified item from the player's inventory.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param item string
 | 
			
		||||
---@param amount number
 | 
			
		||||
---@param slot number
 | 
			
		||||
---@param metadata table
 | 
			
		||||
---@return boolean | nil
 | 
			
		||||
Framework.RemoveItem = function(src, item, amount, slot, metadata)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    TriggerClientEvent("community_bridge:client:inventory:updateInventory", src, { action = "remove", item = item, count = amount, slot = slot, metadata = metadata })
 | 
			
		||||
    return player.Functions.RemoveItem(item, amount, slot or nil)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Framework.SetMetadata(src, item, slot, metadata)
 | 
			
		||||
-- Sets the metadata for the specified item in the player's inventory.
 | 
			
		||||
-- Notes, this is kinda a jank workaround. with the framework aside from updating the entire table theres not really a better way
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param item string
 | 
			
		||||
---@param slot number
 | 
			
		||||
---@param metadata table
 | 
			
		||||
---@return boolean | nil
 | 
			
		||||
Framework.SetMetadata = function(src, item, slot, metadata)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    local slotFinder = Framework.GetPlayerInventory(src)
 | 
			
		||||
    local freeSlot = Table.FindFirstUnoccupiedSlot(slotFinder)
 | 
			
		||||
    local itemSlot = slot or nil
 | 
			
		||||
    if itemSlot == nil then
 | 
			
		||||
        for _, v in pairs(slotFinder) do
 | 
			
		||||
            if v.name == item then
 | 
			
		||||
                slot = v.slot
 | 
			
		||||
                break
 | 
			
		||||
            end
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
    if not player.Functions.RemoveItem(item, 1, itemSlot) then return false end
 | 
			
		||||
    return player.Functions.AddItem(item, 1, slot, metadata)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will get all owned vehicles for the player
 | 
			
		||||
---@param src number
 | 
			
		||||
---@return table
 | 
			
		||||
Framework.GetOwnedVehicles = function(src)
 | 
			
		||||
    local citizenId = Framework.GetPlayerIdentifier(src)
 | 
			
		||||
    local result = MySQL.Sync.fetchAll("SELECT vehicle, plate FROM player_vehicles WHERE citizenid = '" .. citizenId .. "'")
 | 
			
		||||
    local vehicles = {}
 | 
			
		||||
    for i = 1, #result do
 | 
			
		||||
        local vehicle = result[i].vehicle
 | 
			
		||||
        local plate = result[i].plate
 | 
			
		||||
        table.insert(vehicles, { vehicle = vehicle, plate = plate })
 | 
			
		||||
    end
 | 
			
		||||
    return vehicles
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
-- Framework.RegisterUsableItem(item, cb)
 | 
			
		||||
-- Registers a usable item with a callback function.
 | 
			
		||||
---@param itemName string
 | 
			
		||||
---@param cb function
 | 
			
		||||
Framework.RegisterUsableItem = function(itemName, cb)
 | 
			
		||||
    local func = function(src, item, itemData)
 | 
			
		||||
        itemData = itemData or item
 | 
			
		||||
        itemData.metadata = itemData.metadata or itemData.info or {}
 | 
			
		||||
        itemData.slot = itemData.id or itemData.slot
 | 
			
		||||
        cb(src, itemData)
 | 
			
		||||
    end
 | 
			
		||||
    QBCore.Functions.CreateUseableItem(itemName, func)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
RegisterNetEvent("QBCore:Server:OnPlayerLoaded", function(src)
 | 
			
		||||
    src = src or source
 | 
			
		||||
    TriggerEvent("community_bridge:Server:OnPlayerLoaded", src)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
RegisterNetEvent("QBCore:Server:OnPlayerUnload", function(src)
 | 
			
		||||
    src = src or source
 | 
			
		||||
    TriggerEvent("community_bridge:Server:OnPlayerUnload", src)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
AddEventHandler("playerDropped", function()
 | 
			
		||||
    local src = source
 | 
			
		||||
    TriggerEvent("community_bridge:Server:OnPlayerUnload", src)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
Framework.Commands = {}
 | 
			
		||||
Framework.Commands.Add = function(name, help, arguments, argsrequired, callback, permission, ...)
 | 
			
		||||
    QBCore.Commands.Add(name, help, arguments, argsrequired, callback, permission, ...)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return Framework
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,189 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
if GetResourceState('qbx_core') ~= 'started' then return end
 | 
			
		||||
 | 
			
		||||
QBox = exports.qbx_core
 | 
			
		||||
 | 
			
		||||
Framework = Framework or {}
 | 
			
		||||
 | 
			
		||||
---This will get the name of the framework being used (if a supported framework).
 | 
			
		||||
---@return string
 | 
			
		||||
Framework.GetFrameworkName = function()
 | 
			
		||||
    return 'qbx_core'
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return true if the player is loaded, false otherwise.
 | 
			
		||||
---This could be useful in scripts that rely on player loaded events and offer a debug mode to hit this function.
 | 
			
		||||
---@return boolean
 | 
			
		||||
Framework.GetIsPlayerLoaded = function()
 | 
			
		||||
    return LocalPlayer.state.isLoggedIn or false
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return a table of the player data, this will be in the framework format.
 | 
			
		||||
---This is mainly for internal bridge use and should be avoided.
 | 
			
		||||
---@return table
 | 
			
		||||
Framework.GetPlayerData = function()
 | 
			
		||||
    return QBox.GetPlayerData()
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return a table of all the jobs in the framework.
 | 
			
		||||
---@return table
 | 
			
		||||
Framework.GetFrameworkJobs = function()
 | 
			
		||||
    return QBox.GetJobs()
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will get the players birth date
 | 
			
		||||
---@return string
 | 
			
		||||
Framework.GetPlayerDob = function()
 | 
			
		||||
    local playerData = Framework.GetPlayerData()
 | 
			
		||||
    return playerData.charinfo.birthdate
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Will Display the help text message on the screen
 | 
			
		||||
---@param message string
 | 
			
		||||
---@param position string
 | 
			
		||||
---@return nil
 | 
			
		||||
Framework.ShowHelpText = function(message, position)
 | 
			
		||||
    return exports.ox_lib:showTextUI(message, { position = position or 'top-center' })
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will hide the help text message on the screen
 | 
			
		||||
---@return nil
 | 
			
		||||
Framework.HideHelpText = function()
 | 
			
		||||
    return exports.ox_lib:hideTextUI()
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return the players metadata for the specified metadata key.
 | 
			
		||||
---@param metadata table | string
 | 
			
		||||
---@return table | string | number | boolean
 | 
			
		||||
Framework.GetPlayerMetaData = function(metadata)
 | 
			
		||||
    local playerData = Framework.GetPlayerData()
 | 
			
		||||
    return playerData.metadata[metadata]
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will send a notification to the player.
 | 
			
		||||
---@param message string
 | 
			
		||||
---@param type string
 | 
			
		||||
---@param time number
 | 
			
		||||
---@return nil
 | 
			
		||||
Framework.Notify = function(message, type, time)
 | 
			
		||||
    return QBox:Notify("Notification", type, time, message)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will get the players identifier (citizenid) etc.
 | 
			
		||||
---@return string
 | 
			
		||||
Framework.GetPlayerIdentifier = function()
 | 
			
		||||
    return Framework.GetPlayerData().citizenid
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will get the players name (first and last).
 | 
			
		||||
---@return string
 | 
			
		||||
---@return string
 | 
			
		||||
Framework.GetPlayerName = function()
 | 
			
		||||
    local playerData = Framework.GetPlayerData()
 | 
			
		||||
    return playerData.charinfo.firstname, playerData.charinfo.lastname
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Depricated : This will return the players job name, job label, job grade label and job grade level
 | 
			
		||||
---@return string
 | 
			
		||||
---@return string
 | 
			
		||||
---@return string
 | 
			
		||||
---@return string
 | 
			
		||||
Framework.GetPlayerJob = function()
 | 
			
		||||
    local playerData = Framework.GetPlayerData()
 | 
			
		||||
    return playerData.job.name, playerData.job.label, playerData.job.grade.name, playerData.job.grade.level
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return the players job name, job label, job grade label job grade level, boss status, and duty status in a table
 | 
			
		||||
---@return table
 | 
			
		||||
Framework.GetPlayerJobData = function()
 | 
			
		||||
    local playerData = Framework.GetPlayerData()
 | 
			
		||||
    local jobData = playerData.job
 | 
			
		||||
    return {
 | 
			
		||||
        jobName = jobData.name,
 | 
			
		||||
        jobLabel = jobData.label,
 | 
			
		||||
        gradeName = jobData.grade.name,
 | 
			
		||||
        gradeLabel = jobData.grade.name,
 | 
			
		||||
        gradeRank = jobData.grade.level,
 | 
			
		||||
        boss = jobData.isboss,
 | 
			
		||||
        onDuty = jobData.onduty,
 | 
			
		||||
    }
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return the players inventory as a table in the ox_inventory style flormat.
 | 
			
		||||
---@return table
 | 
			
		||||
Framework.GetPlayerInventory = function()
 | 
			
		||||
    return Framework.GetPlayerData().items
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return the players money by type, I recommend not useing this as its the client and not secure or to be trusted.
 | 
			
		||||
---Use case is for a ui or a menu I guess.
 | 
			
		||||
---@param _type string
 | 
			
		||||
---@return number
 | 
			
		||||
Framework.GetAccountBalance = function(_type)
 | 
			
		||||
    local player = Framework.GetPlayerData()
 | 
			
		||||
    if not player then return 0 end
 | 
			
		||||
    local account = player.money
 | 
			
		||||
    if _type == 'money' then _type = 'cash' end
 | 
			
		||||
    return account[_type] or 0
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return the vehicle properties for the specified vehicle.
 | 
			
		||||
---@param vehicle number
 | 
			
		||||
---@return table
 | 
			
		||||
Framework.GetVehicleProperties = function(vehicle)
 | 
			
		||||
    if not vehicle or not DoesEntityExist(vehicle) then return {} end
 | 
			
		||||
    local vehicleProps = lib.getVehicleProperties(vehicle)
 | 
			
		||||
    return vehicleProps or {}
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will set the vehicle properties for the specified vehicle.
 | 
			
		||||
---@param vehicle number
 | 
			
		||||
---@param properties table
 | 
			
		||||
---@return boolean
 | 
			
		||||
Framework.SetVehicleProperties = function(vehicle, properties)
 | 
			
		||||
    if not vehicle or not DoesEntityExist(vehicle) then return false end
 | 
			
		||||
    if not properties then return false end
 | 
			
		||||
    if NetworkGetEntityIsNetworked(vehicle) then
 | 
			
		||||
        local vehNetID = NetworkGetNetworkIdFromEntity(vehicle)
 | 
			
		||||
        local entOwner = GetPlayerServerId(NetworkGetEntityOwner(vehNetID))
 | 
			
		||||
        if entOwner ~= GetPlayerServerId(PlayerId()) then
 | 
			
		||||
            NetworkRequestControlOfEntity(vehicle)
 | 
			
		||||
            local count = 0
 | 
			
		||||
            while not NetworkHasControlOfEntity(vehicle) and count < 3000 do
 | 
			
		||||
                Wait(1)
 | 
			
		||||
                count = count + 1
 | 
			
		||||
            end
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
    return true, lib.setVehicleProperties(vehicle, properties)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return the item count for the specified item in the players inventory.
 | 
			
		||||
---@param item string
 | 
			
		||||
---@return number
 | 
			
		||||
Framework.GetItemCount = function(item)
 | 
			
		||||
    -- This seems to be exclusively for ox_inventory, if other inventories are used, they need to be bridged in the inventory module. Until then we will return 0 and a print.
 | 
			
		||||
    return 0, print("Community_bridge:WARN: GetItemCount is not implemented for this framework, please use the inventory module to get the item count. If you are using a diffrent inventory please let us know so we can bridge it and have less nonsense.")
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will get a players dead status.
 | 
			
		||||
---@return boolean
 | 
			
		||||
Framework.GetIsPlayerDead = function()
 | 
			
		||||
    local platerData = Framework.GetPlayerData()
 | 
			
		||||
    return platerData.metadata["isdead"] or platerData.metadata["inlaststand"]
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function()
 | 
			
		||||
    Wait(1500)
 | 
			
		||||
    TriggerEvent('community_bridge:Client:OnPlayerLoaded')
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
RegisterNetEvent('QBCore:Client:OnPlayerUnload', function()
 | 
			
		||||
    TriggerEvent('community_bridge:Client:OnPlayerUnload')
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
RegisterNetEvent('QBCore:Client:OnJobUpdate', function(data)
 | 
			
		||||
    TriggerEvent('community_bridge:Client:OnPlayerJobUpdate', data.name, data.label, data.grade.name, data.grade.level)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
return Framework
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,489 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
if GetResourceState('qbx_core') ~= 'started' then return end
 | 
			
		||||
 | 
			
		||||
Framework = Framework or {}
 | 
			
		||||
 | 
			
		||||
local QBox = exports.qbx_core
 | 
			
		||||
 | 
			
		||||
---Returns the name of the framework being used (if a supported framework).
 | 
			
		||||
---@return string
 | 
			
		||||
Framework.GetFrameworkName = function()
 | 
			
		||||
    return 'qbx_core'
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return if the player is an admin in the framework.
 | 
			
		||||
---@param src any
 | 
			
		||||
---@return boolean
 | 
			
		||||
Framework.GetIsFrameworkAdmin = function(src)
 | 
			
		||||
    if not src then return false end
 | 
			
		||||
    return IsPlayerAceAllowed(src, 'admin')
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Returns the player date of birth.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@return string|nil
 | 
			
		||||
Framework.GetPlayerDob = function(src)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    local playerData = player.PlayerData
 | 
			
		||||
    return playerData.charinfo.birthdate
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
--- Returns the player data of the specified source.
 | 
			
		||||
---@param src any
 | 
			
		||||
---@return table | nil
 | 
			
		||||
Framework.GetPlayer = function(src)
 | 
			
		||||
    local player = QBox:GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    return player
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Returns a table of the jobs in the framework.
 | 
			
		||||
---@return table
 | 
			
		||||
Framework.GetFrameworkJobs = function()
 | 
			
		||||
    return QBox.GetJobs()
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Returns the citizen ID of the player.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@return string | boolean | nil
 | 
			
		||||
Framework.GetPlayerIdentifier = function(src)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    local playerData = player.PlayerData
 | 
			
		||||
    if not playerData then return false end
 | 
			
		||||
    return playerData.citizenid
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return a table of all logged in players
 | 
			
		||||
---@return table
 | 
			
		||||
Framework.GetPlayers = function()
 | 
			
		||||
    local players = QBox:GetQBPlayers()
 | 
			
		||||
    local playerList = {}
 | 
			
		||||
    for src, _ in pairs(players) do
 | 
			
		||||
        table.insert(playerList, src)
 | 
			
		||||
    end
 | 
			
		||||
    return playerList
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Returns the first and last name of the player.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@return string | nil
 | 
			
		||||
---@return string | nil
 | 
			
		||||
Framework.GetPlayerName = function(src)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    local playerData = player.PlayerData
 | 
			
		||||
    return playerData.charinfo.firstname, playerData.charinfo.lastname
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Returns a table of items matching the specified name and if passed metadata from the player's inventory.
 | 
			
		||||
---returns {name = v.name, count = v.amount, metadata = v.info, slot = v.slot}
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param item string
 | 
			
		||||
---@param metadata table
 | 
			
		||||
---@return table|nil
 | 
			
		||||
Framework.GetItem = function(src, item, metadata)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    local playerInventory = player.PlayerData.items
 | 
			
		||||
    local repackedTable = {}
 | 
			
		||||
    for _, v in pairs(playerInventory) do
 | 
			
		||||
        if v.name == item and (not metadata or v.info == metadata) then
 | 
			
		||||
            table.insert(repackedTable, {
 | 
			
		||||
                name = v.name,
 | 
			
		||||
                count = v.amount,
 | 
			
		||||
                metadata = v.info,
 | 
			
		||||
                slot = v.slot,
 | 
			
		||||
            })
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
    return repackedTable
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Returns the count of items matching the specified name and if passed metadata from the player's inventory.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param item string
 | 
			
		||||
---@param metadata table
 | 
			
		||||
---@return number | nil
 | 
			
		||||
Framework.GetItemCount = function(src, item, metadata)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    local playerInventory = player.PlayerData.items
 | 
			
		||||
    local count = 0
 | 
			
		||||
    for _, v in pairs(playerInventory) do
 | 
			
		||||
        if v.name == item and (not metadata or v.info == metadata) then
 | 
			
		||||
            count = count + v.amount
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
    return count
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Returns boolean if the player has the specified item in their inventory.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param item string
 | 
			
		||||
---@return boolean
 | 
			
		||||
Framework.HasItem = function(src, item)
 | 
			
		||||
    local getCount = Framework.GetItemCount(src, item, nil)
 | 
			
		||||
    return getCount > 0
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Returns the entire inventory of the player as a table.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@return table | nil
 | 
			
		||||
Framework.GetPlayerInventory = function(src)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    local playerItems = player.PlayerData.items
 | 
			
		||||
    local repackedTable = {}
 | 
			
		||||
    for _, v in pairs(playerItems) do
 | 
			
		||||
        table.insert(repackedTable, {
 | 
			
		||||
            name = v.name,
 | 
			
		||||
            count = v.amount,
 | 
			
		||||
            metadata = v.metadata,
 | 
			
		||||
            slot = v.slot,
 | 
			
		||||
        })
 | 
			
		||||
    end
 | 
			
		||||
    return repackedTable
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Adds the specified metadata key and number value to the player's data.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param metadata string
 | 
			
		||||
---@param value string
 | 
			
		||||
---@return boolean | nil
 | 
			
		||||
Framework.SetPlayerMetadata = function(src, metadata, value)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    player.Functions.SetMetaData(metadata, value)
 | 
			
		||||
    return true
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Gets the specified metadata key to the player's data.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param metadata string
 | 
			
		||||
---@return string | boolean | nil
 | 
			
		||||
Framework.GetPlayerMetadata = function(src, metadata)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    local playerData = player.PlayerData
 | 
			
		||||
    return playerData.metadata[metadata] or false
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Adds the specified value to the player's stress level and updates the client HUD.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param value number
 | 
			
		||||
---@return number | nil
 | 
			
		||||
Framework.AddStress = function(src, value)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    local playerData = player.PlayerData
 | 
			
		||||
    local newStress = playerData.metadata.stress + value
 | 
			
		||||
    player.Functions.SetMetaData('stress', Math.Clamp(newStress, 0, 100))
 | 
			
		||||
    TriggerClientEvent('hud:client:UpdateStress', src, newStress)
 | 
			
		||||
    return newStress
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Removes the specified value from the player's stress level and updates the client HUD.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param value number
 | 
			
		||||
---@return number | nil
 | 
			
		||||
Framework.RemoveStress = function(src, value)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    local playerData = player.PlayerData
 | 
			
		||||
    local newStress = (playerData.metadata.stress or 0) - value
 | 
			
		||||
    player.Functions.SetMetaData('stress', Math.Clamp(newStress, 0, 100))
 | 
			
		||||
    TriggerClientEvent('hud:client:UpdateStress', src, newStress)
 | 
			
		||||
    return newStress
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Adds the specified value from the player's hunger level.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param value number
 | 
			
		||||
---@return number | nil
 | 
			
		||||
Framework.AddHunger = function(src, value)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    local playerData = player.PlayerData
 | 
			
		||||
    local newHunger = (playerData.metadata.hunger or 0) + value
 | 
			
		||||
    player.Functions.SetMetaData('hunger', Math.Clamp(newHunger, 0, 100))
 | 
			
		||||
    --TriggerClientEvent('hud:client:UpdateStress', src, newStress)
 | 
			
		||||
    return newHunger
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Adds the specified value from the player's thirst level.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param value number
 | 
			
		||||
---@return number | nil
 | 
			
		||||
Framework.AddThirst = function(src, value)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    local playerData = player.PlayerData
 | 
			
		||||
    local newThirst = (playerData.metadata.thirst or 0) + value
 | 
			
		||||
    player.Functions.SetMetaData('thirst', Math.Clamp(newThirst, 0, 100))
 | 
			
		||||
    --TriggerClientEvent('hud:client:UpdateStress', src, newStress)
 | 
			
		||||
    return newThirst
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return the players hunger level.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@return number | nil
 | 
			
		||||
Framework.GetHunger = function(src)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    local playerData = player.PlayerData
 | 
			
		||||
    local newHunger = (playerData.metadata.hunger or 0)
 | 
			
		||||
    return newHunger
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return a boolean if the player is dead or in last stand.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@return boolean|nil
 | 
			
		||||
Framework.GetIsPlayerDead = function(src)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    local playerData = player.PlayerData
 | 
			
		||||
    return playerData.metadata.isdead or false
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will revive a player, if the player is dead or in last stand.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@return boolean
 | 
			
		||||
Framework.RevivePlayer = function(src)
 | 
			
		||||
    src = tonumber(src)
 | 
			
		||||
    if not src then return false end
 | 
			
		||||
    TriggerClientEvent('hospital:client:Revive', src)
 | 
			
		||||
    return true
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return the players thirst level.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@return number| nil
 | 
			
		||||
Framework.GetThirst = function(src)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    local playerData = player.PlayerData
 | 
			
		||||
    local newThirst = (playerData.metadata.thirst or 0)
 | 
			
		||||
    return newThirst
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Returns the phone number of the player.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@return string | nil
 | 
			
		||||
Framework.GetPlayerPhone = function(src)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    local playerData = player.PlayerData
 | 
			
		||||
    return playerData.charinfo.phone
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Returns the gang name of the player.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@return string | nil
 | 
			
		||||
Framework.GetPlayerGang = function(src)
 | 
			
		||||
    local player = Framework.GetPlayer(src).PlayerData
 | 
			
		||||
    return player.gang.name
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return a table of all players with the specified job.
 | 
			
		||||
---@param job string
 | 
			
		||||
---@return table
 | 
			
		||||
Framework.GetPlayersByJob = function(job)
 | 
			
		||||
    local playerList = {}
 | 
			
		||||
    local players = QBox:GetQBPlayers()
 | 
			
		||||
    for src, player in pairs(players) do
 | 
			
		||||
        if player.PlayerData.job.name == job then
 | 
			
		||||
            table.insert(playerList, src)
 | 
			
		||||
        end
 | 
			
		||||
    end
 | 
			
		||||
    return playerList
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Depricated: Returns the job name, label, grade name, and grade level of the player.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@return string | string | string | number | nil
 | 
			
		||||
---@return string | string | string | number | nil
 | 
			
		||||
---@return string | string | string | number | nil
 | 
			
		||||
---@return string | string | string | number | nil
 | 
			
		||||
Framework.GetPlayerJob = function(src)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    local playerData = player.PlayerData
 | 
			
		||||
    return playerData.job.name, playerData.job.label, playerData.job.grade.name, playerData.job.grade.level
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will return the players job name, job label, job grade label job grade level, boss status, and duty status in a table
 | 
			
		||||
---@param src number
 | 
			
		||||
---@return table | nil
 | 
			
		||||
Framework.GetPlayerJobData = function(src)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    local playerData = player.PlayerData
 | 
			
		||||
    local jobData = playerData.job
 | 
			
		||||
    return {
 | 
			
		||||
        jobName = jobData.name,
 | 
			
		||||
        jobLabel = jobData.label,
 | 
			
		||||
        gradeName = jobData.grade.name,
 | 
			
		||||
        gradeLabel = jobData.grade.name,
 | 
			
		||||
        gradeRank = jobData.grade.level,
 | 
			
		||||
        boss = jobData.isboss,
 | 
			
		||||
        onDuty = jobData.onduty,
 | 
			
		||||
    }
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Sets the player's job to the specified name and grade.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param name string
 | 
			
		||||
---@param grade string
 | 
			
		||||
---@return boolean | nil
 | 
			
		||||
Framework.SetPlayerJob = function(src, name, grade)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    return player.Functions.SetJob(name, grade)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will toggle the duty status of the player.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param status boolean
 | 
			
		||||
Framework.SetPlayerDuty = function(src, status)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    local playerData = player.PlayerData
 | 
			
		||||
    QBox:SetJobDuty(playerData.citizenid, status)
 | 
			
		||||
    TriggerEvent('QBCore:Server:SetDuty', src, player.PlayerData.job.onduty)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Returns the players duty status.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@return boolean | nil
 | 
			
		||||
Framework.GetPlayerDuty = function(src)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    local playerData = player.PlayerData
 | 
			
		||||
    if not playerData.job.onduty then return false end
 | 
			
		||||
    return true
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Adds the specified amount to the player's account balance of the specified type.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param _type string
 | 
			
		||||
---@param amount number
 | 
			
		||||
---@return boolean | nil
 | 
			
		||||
Framework.AddAccountBalance = function(src, _type, amount)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    if _type == 'money' then _type = 'cash' end
 | 
			
		||||
    return player.Functions.AddMoney(_type, amount)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Removes the specified amount from the player's account balance of the specified type.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param _type string
 | 
			
		||||
---@param amount number
 | 
			
		||||
---@return boolean | nil
 | 
			
		||||
Framework.RemoveAccountBalance = function(src, _type, amount)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    if _type == 'money' then _type = 'cash' end
 | 
			
		||||
    return player.Functions.RemoveMoney(_type, amount)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Returns the player's account balance of the specified type.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param _type string
 | 
			
		||||
---@return number | nil
 | 
			
		||||
Framework.GetAccountBalance = function(src, _type)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    local playerData = player.PlayerData
 | 
			
		||||
    if _type == 'money' then _type = 'cash' end
 | 
			
		||||
    return playerData.money[_type]
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Adds the specified item to the player's inventory.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param item string
 | 
			
		||||
---@param amount number
 | 
			
		||||
---@param slot number
 | 
			
		||||
---@param metadata table
 | 
			
		||||
---@return boolean | nil
 | 
			
		||||
Framework.AddItem = function(src, item, amount, slot, metadata)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    TriggerClientEvent("community_bridge:client:inventory:updateInventory", src, { action = "add", item = item, count = amount, slot = slot, metadata = metadata })
 | 
			
		||||
    return player.Functions.AddItem(item, amount, slot, metadata)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Removes the specified item from the player's inventory.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param item string
 | 
			
		||||
---@param amount number
 | 
			
		||||
---@param slot number
 | 
			
		||||
---@param metadata table
 | 
			
		||||
---@return boolean | nil
 | 
			
		||||
Framework.RemoveItem = function(src, item, amount, slot, metadata)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    TriggerClientEvent("community_bridge:client:inventory:updateInventory", src, { action = "remove", item = item, count = amount, slot = slot, metadata = metadata })
 | 
			
		||||
    return player.Functions.RemoveItem(item, amount, slot)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Sets the metadata for the specified item in the player's inventory.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param item string
 | 
			
		||||
---@param slot number
 | 
			
		||||
---@param metadata table
 | 
			
		||||
---@return boolean | nil
 | 
			
		||||
Framework.SetMetadata = function(src, item, slot, metadata)
 | 
			
		||||
    local player = Framework.GetPlayer(src)
 | 
			
		||||
    if not player then return end
 | 
			
		||||
    player.Functions.RemoveItem(item, 1, slot)
 | 
			
		||||
    return player.Functions.AddItem(item, 1, slot, metadata)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Returns a table of owned vehicles for the player. format is {vehicle = vehicle, plate = plate}
 | 
			
		||||
---@param src number
 | 
			
		||||
---@return table
 | 
			
		||||
Framework.GetOwnedVehicles = function(src)
 | 
			
		||||
    local citizenId = Framework.GetPlayerIdentifier(src)
 | 
			
		||||
    local result = MySQL.Sync.fetchAll("SELECT vehicle, plate FROM player_vehicles WHERE citizenid = '" .. citizenId .. "'")
 | 
			
		||||
    local vehicles = {}
 | 
			
		||||
    for i = 1, #result do
 | 
			
		||||
        local vehicle = result[i].vehicle
 | 
			
		||||
        local plate = result[i].plate
 | 
			
		||||
        table.insert(vehicles, { vehicle = vehicle, plate = plate })
 | 
			
		||||
    end
 | 
			
		||||
    return vehicles
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---Registers a usable item with a callback function.
 | 
			
		||||
---@param itemName string
 | 
			
		||||
---@param cb function
 | 
			
		||||
---@return function
 | 
			
		||||
Framework.RegisterUsableItem = function(itemName, cb)
 | 
			
		||||
    local func = function(src, item, itemData)
 | 
			
		||||
        itemData = itemData or item
 | 
			
		||||
        itemData.metadata = itemData.metadata or itemData.info or {}
 | 
			
		||||
        itemData.slot = itemData.id or itemData.slot
 | 
			
		||||
        cb(src, itemData)
 | 
			
		||||
    end
 | 
			
		||||
    return QBox:CreateUseableItem(itemName, func)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
RegisterNetEvent("QBCore:Server:OnPlayerLoaded", function(src)
 | 
			
		||||
    src = src or source
 | 
			
		||||
    TriggerEvent("community_bridge:Server:OnPlayerLoaded", src)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
RegisterNetEvent("QBCore:Server:OnPlayerUnload", function(src)
 | 
			
		||||
    src = src or source
 | 
			
		||||
    TriggerEvent("community_bridge:Server:OnPlayerUnload", src)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
AddEventHandler("playerDropped", function()
 | 
			
		||||
    local src = source
 | 
			
		||||
    TriggerEvent("community_bridge:Server:OnPlayerUnload", src)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
return Framework
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,27 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
Fuel = Fuel or {}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
---This will get the name of the Fuel being used (if a supported Fuel).
 | 
			
		||||
---@return string
 | 
			
		||||
Fuel.GetResourceName = function()
 | 
			
		||||
    return 'default'
 | 
			
		||||
end
 | 
			
		||||
---This will get the fuel level of the vehicle.
 | 
			
		||||
---@param vehicle number The vehicle entity ID.
 | 
			
		||||
---@return number fuel The fuel level of the vehicle.
 | 
			
		||||
Fuel.GetFuel = function(vehicle)
 | 
			
		||||
    if not DoesEntityExist(vehicle) then return 0.0 end
 | 
			
		||||
    return GetVehicleFuelLevel(vehicle)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will set the fuel level of the vehicle.
 | 
			
		||||
---@param vehicle number The vehicle entity ID.
 | 
			
		||||
---@param fuel number The fuel level to set.
 | 
			
		||||
---@return nil
 | 
			
		||||
Fuel.SetFuel = function(vehicle, fuel)
 | 
			
		||||
    if not DoesEntityExist(vehicle) then return end
 | 
			
		||||
    return SetVehicleFuelLevel(vehicle, fuel)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return Fuel
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,29 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
local resourceName = "BigDaddy-Fuel"
 | 
			
		||||
if GetResourceState(resourceName) == 'missing' then return end
 | 
			
		||||
Fuel = Fuel or {}
 | 
			
		||||
 | 
			
		||||
---This will get the name of the Fuel being used (if a supported Fuel).
 | 
			
		||||
---@return string
 | 
			
		||||
Fuel.GetResourceName = function()
 | 
			
		||||
    return resourceName
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will get the fuel level of the vehicle.
 | 
			
		||||
---@param vehicle number The vehicle entity ID.
 | 
			
		||||
---@return number fuel The fuel level of the vehicle.
 | 
			
		||||
Fuel.GetFuel = function(vehicle)
 | 
			
		||||
    if not DoesEntityExist(vehicle) then return 0.0 end
 | 
			
		||||
    return exports['BigDaddy-Fuel']:GetFuel(vehicle)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will set the fuel level of the vehicle.
 | 
			
		||||
---@param vehicle number The vehicle entity ID.
 | 
			
		||||
---@param fuel number The fuel level to set.
 | 
			
		||||
---@return nil
 | 
			
		||||
Fuel.SetFuel = function(vehicle, fuel)
 | 
			
		||||
    if not DoesEntityExist(vehicle) then return end
 | 
			
		||||
    exports['BigDaddy-Fuel']:SetFuel(vehicle, fuel)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return Fuel
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,29 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
local resourceName = "cdn-fuel"
 | 
			
		||||
if GetResourceState(resourceName) == 'missing' then return end
 | 
			
		||||
Fuel = Fuel or {}
 | 
			
		||||
 | 
			
		||||
---This will get the name of the Fuel being used (if a supported Fuel).
 | 
			
		||||
---@return string
 | 
			
		||||
Fuel.GetResourceName = function()
 | 
			
		||||
    return resourceName
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will get the fuel level of the vehicle.
 | 
			
		||||
---@param vehicle number The vehicle entity ID.
 | 
			
		||||
---@return number fuel The fuel level of the vehicle.
 | 
			
		||||
Fuel.GetFuel = function(vehicle)
 | 
			
		||||
    if not DoesEntityExist(vehicle) then return 0.0 end
 | 
			
		||||
    return exports['cdn-fuel']:GetFuel(vehicle)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will set the fuel level of the vehicle.
 | 
			
		||||
---@param vehicle number The vehicle entity ID.
 | 
			
		||||
---@param fuel number The fuel level to set.
 | 
			
		||||
---@return nil
 | 
			
		||||
Fuel.SetFuel = function(vehicle, fuel)
 | 
			
		||||
    if not DoesEntityExist(vehicle) then return end
 | 
			
		||||
    return exports['cdn-fuel']:SetFuel(vehicle, fuel)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return Fuel
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,29 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
local resourceName = "esx-sna-fuel"
 | 
			
		||||
if GetResourceState(resourceName) == 'missing' then return end
 | 
			
		||||
Fuel = Fuel or {}
 | 
			
		||||
 | 
			
		||||
---This will get the name of the Fuel being used (if a supported Fuel).
 | 
			
		||||
---@return string
 | 
			
		||||
Fuel.GetResourceName = function()
 | 
			
		||||
    return resourceName
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will get the fuel level of the vehicle.
 | 
			
		||||
---@param vehicle number The vehicle entity ID.
 | 
			
		||||
---@return number fuel The fuel level of the vehicle.
 | 
			
		||||
Fuel.GetFuel = function(vehicle)
 | 
			
		||||
    if not DoesEntityExist(vehicle) then return 0.0 end
 | 
			
		||||
    return exports['esx-sna-fuel']:GetFuel(vehicle)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will set the fuel level of the vehicle.
 | 
			
		||||
---@param vehicle number The vehicle entity ID.
 | 
			
		||||
---@param fuel number The fuel level to set.
 | 
			
		||||
---@return nil
 | 
			
		||||
Fuel.SetFuel = function(vehicle, fuel)
 | 
			
		||||
    if not DoesEntityExist(vehicle) then return end
 | 
			
		||||
    exports['esx-sna-fuel']:SetFuel(vehicle, fuel)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return Fuel
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,29 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
local resourceName = "lc_fuel"
 | 
			
		||||
if GetResourceState(resourceName) == 'missing' then return end
 | 
			
		||||
Fuel = Fuel or {}
 | 
			
		||||
 | 
			
		||||
---This will get the name of the Fuel being used (if a supported Fuel).
 | 
			
		||||
---@return string
 | 
			
		||||
Fuel.GetResourceName = function()
 | 
			
		||||
    return resourceName
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will get the fuel level of the vehicle.
 | 
			
		||||
---@param vehicle number The vehicle entity ID.
 | 
			
		||||
---@return number fuel The fuel level of the vehicle.
 | 
			
		||||
Fuel.GetFuel = function(vehicle)
 | 
			
		||||
    if not DoesEntityExist(vehicle) then return 0.0 end
 | 
			
		||||
    return exports["lc_fuel"]:GetFuel(vehicle)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will set the fuel level of the vehicle.
 | 
			
		||||
---@param vehicle number The vehicle entity ID.
 | 
			
		||||
---@param fuel number The fuel level to set.
 | 
			
		||||
---@return nil
 | 
			
		||||
Fuel.SetFuel = function(vehicle, fuel, type)
 | 
			
		||||
    if not DoesEntityExist(vehicle) then return end
 | 
			
		||||
    return exports["lc_fuel"]:SetFuel(vehicle, fuel)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return Fuel
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,29 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
local resourceName = "LegacyFuel"
 | 
			
		||||
if GetResourceState(resourceName) == 'missing' then return end
 | 
			
		||||
Fuel = Fuel or {}
 | 
			
		||||
 | 
			
		||||
---This will get the name of the Fuel being used (if a supported Fuel).
 | 
			
		||||
---@return string
 | 
			
		||||
Fuel.GetResourceName = function()
 | 
			
		||||
    return resourceName
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will get the fuel level of the vehicle.
 | 
			
		||||
---@param vehicle number The vehicle entity ID.
 | 
			
		||||
---@return number fuel The fuel level of the vehicle.
 | 
			
		||||
Fuel.GetFuel = function(vehicle)
 | 
			
		||||
    if not DoesEntityExist(vehicle) then return 0.0 end
 | 
			
		||||
    return exports['LegacyFuel']:GetFuel(vehicle)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will set the fuel level of the vehicle.
 | 
			
		||||
---@param vehicle number The vehicle entity ID.
 | 
			
		||||
---@param fuel number The fuel level to set.
 | 
			
		||||
---@return nil
 | 
			
		||||
Fuel.SetFuel = function(vehicle, fuel, type)
 | 
			
		||||
    if not DoesEntityExist(vehicle) then return end
 | 
			
		||||
    return exports['LegacyFuel']:SetFuel(vehicle, fuel)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return Fuel
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,29 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
local resourceName = "okokGasStation"
 | 
			
		||||
if GetResourceState(resourceName) == 'missing' then return end
 | 
			
		||||
Fuel = Fuel or {}
 | 
			
		||||
 | 
			
		||||
---This will get the name of the Fuel being used (if a supported Fuel).
 | 
			
		||||
---@return string
 | 
			
		||||
Fuel.GetResourceName = function()
 | 
			
		||||
    return resourceName
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will get the fuel level of the vehicle.
 | 
			
		||||
---@param vehicle number The vehicle entity ID.
 | 
			
		||||
---@return number fuel The fuel level of the vehicle.
 | 
			
		||||
Fuel.GetFuel = function(vehicle)
 | 
			
		||||
    if not DoesEntityExist(vehicle) then return 0.0 end
 | 
			
		||||
    return exports['okokGasStation']:GetFuel(vehicle)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will set the fuel level of the vehicle.
 | 
			
		||||
---@param vehicle number The vehicle entity ID.
 | 
			
		||||
---@param fuel number The fuel level to set.
 | 
			
		||||
---@return nil
 | 
			
		||||
Fuel.SetFuel = function(vehicle, fuel, type)
 | 
			
		||||
    if not DoesEntityExist(vehicle) then return end
 | 
			
		||||
    return exports['okokGasStation']:SetFuel(vehicle, fuel)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return Fuel
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,31 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
local resourceName = "ox_fuel"
 | 
			
		||||
if GetResourceState(resourceName) == 'missing' then return end
 | 
			
		||||
Fuel = Fuel or {}
 | 
			
		||||
 | 
			
		||||
---This will get the name of the Fuel being used (if a supported Fuel).
 | 
			
		||||
---@return string
 | 
			
		||||
Fuel.GetResourceName = function()
 | 
			
		||||
    return resourceName
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will get the fuel level of the vehicle.
 | 
			
		||||
---@param vehicle number The vehicle entity ID.
 | 
			
		||||
---@return number fuel The fuel level of the vehicle.
 | 
			
		||||
Fuel.GetFuel = function(vehicle)
 | 
			
		||||
    if not DoesEntityExist(vehicle) then return 0.0 end
 | 
			
		||||
    return Entity(vehicle).state.fuel
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will set the fuel level of the vehicle.
 | 
			
		||||
---@param vehicle number The vehicle entity ID.
 | 
			
		||||
---@param fuel number The fuel level to set.
 | 
			
		||||
---@return nil
 | 
			
		||||
Fuel.SetFuel = function(vehicle, fuel, type)
 | 
			
		||||
    if not DoesEntityExist(vehicle) then return end
 | 
			
		||||
    local currentFuel = Entity(vehicle).state.fuel
 | 
			
		||||
    Entity(vehicle).state.fuel = currentFuel and currentFuel + fuel or fuel
 | 
			
		||||
    return Entity(vehicle).state.fuel
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return Fuel
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,29 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
local resourceName = "ps-fuel"
 | 
			
		||||
if GetResourceState(resourceName) == 'missing' then return end
 | 
			
		||||
Fuel = Fuel or {}
 | 
			
		||||
 | 
			
		||||
---This will get the name of the Fuel being used (if a supported Fuel).
 | 
			
		||||
---@return string
 | 
			
		||||
Fuel.GetResourceName = function()
 | 
			
		||||
    return resourceName
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will get the fuel level of the vehicle.
 | 
			
		||||
---@param vehicle number The vehicle entity ID.
 | 
			
		||||
---@return number fuel The fuel level of the vehicle.
 | 
			
		||||
Fuel.GetFuel = function(vehicle)
 | 
			
		||||
    if not DoesEntityExist(vehicle) then return 0.0 end
 | 
			
		||||
    return exports["ps-fuel"]:GetFuel(vehicle)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will set the fuel level of the vehicle.
 | 
			
		||||
---@param vehicle number The vehicle entity ID.
 | 
			
		||||
---@param fuel number The fuel level to set.
 | 
			
		||||
---@return nil
 | 
			
		||||
Fuel.SetFuel = function(vehicle, fuel, type)
 | 
			
		||||
    if not DoesEntityExist(vehicle) then return end
 | 
			
		||||
    return exports["ps-fuel"]:SetFuel(vehicle, fuel)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return Fuel
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,29 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
local resourceName = "qs-fuelstations"
 | 
			
		||||
if GetResourceState(resourceName) == 'missing' then return end
 | 
			
		||||
Fuel = Fuel or {}
 | 
			
		||||
 | 
			
		||||
---This will get the name of the Fuel being used (if a supported Fuel).
 | 
			
		||||
---@return string
 | 
			
		||||
Fuel.GetResourceName = function()
 | 
			
		||||
    return resourceName
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will get the fuel level of the vehicle.
 | 
			
		||||
---@param vehicle number The vehicle entity ID.
 | 
			
		||||
---@return number fuel The fuel level of the vehicle.
 | 
			
		||||
Fuel.GetFuel = function(vehicle)
 | 
			
		||||
    if not DoesEntityExist(vehicle) then return 0.0 end
 | 
			
		||||
    return exports['qs-fuelstations']:GetFuel(vehicle)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will set the fuel level of the vehicle.
 | 
			
		||||
---@param vehicle number The vehicle entity ID.
 | 
			
		||||
---@param fuel number The fuel level to set.
 | 
			
		||||
---@return nil
 | 
			
		||||
Fuel.SetFuel = function(vehicle, fuel)
 | 
			
		||||
    if not DoesEntityExist(vehicle) then return end
 | 
			
		||||
    return exports['qs-fuelstations']:SetFuel(vehicle, fuel)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return Fuel
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,29 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
local resourceName = "Renewed-Fuel"
 | 
			
		||||
if GetResourceState(resourceName) == 'missing' then return end
 | 
			
		||||
Fuel = Fuel or {}
 | 
			
		||||
 | 
			
		||||
---This will get the name of the Fuel being used (if a supported Fuel).
 | 
			
		||||
---@return string
 | 
			
		||||
Fuel.GetResourceName = function()
 | 
			
		||||
    return resourceName
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will get the fuel level of the vehicle.
 | 
			
		||||
---@param vehicle number The vehicle entity ID.
 | 
			
		||||
---@return number fuel The fuel level of the vehicle.
 | 
			
		||||
Fuel.GetFuel = function(vehicle)
 | 
			
		||||
    if not DoesEntityExist(vehicle) then return 0.0 end
 | 
			
		||||
    return exports['Renewed-Fuel']:GetFuel(vehicle)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will set the fuel level of the vehicle.
 | 
			
		||||
---@param vehicle number The vehicle entity ID.
 | 
			
		||||
---@param fuel number The fuel level to set.
 | 
			
		||||
---@return nil
 | 
			
		||||
Fuel.SetFuel = function(vehicle, fuel, type)
 | 
			
		||||
    if not DoesEntityExist(vehicle) then return end
 | 
			
		||||
    return exports['Renewed-Fuel']:SetFuel(vehicle, fuel)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return Fuel
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,30 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
local resourceName = "ti_fuel"
 | 
			
		||||
if GetResourceState(resourceName) == 'missing' then return end
 | 
			
		||||
Fuel = Fuel or {}
 | 
			
		||||
 | 
			
		||||
---This will get the name of the Fuel being used (if a supported Fuel).
 | 
			
		||||
---@return string
 | 
			
		||||
Fuel.GetResourceName = function()
 | 
			
		||||
    return resourceName
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will get the fuel level of the vehicle.
 | 
			
		||||
---@param vehicle number The vehicle entity ID.
 | 
			
		||||
---@return number fuel The fuel level of the vehicle.
 | 
			
		||||
Fuel.GetFuel = function(vehicle)
 | 
			
		||||
    if not DoesEntityExist(vehicle) then return 0.0 end
 | 
			
		||||
    local level, _ = exports["ti_fuel"]:getFuel(vehicle)
 | 
			
		||||
    return level
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will set the fuel level of the vehicle.
 | 
			
		||||
---@param vehicle number The vehicle entity ID.
 | 
			
		||||
---@param fuel number The fuel level to set.
 | 
			
		||||
---@return nil
 | 
			
		||||
Fuel.SetFuel = function(vehicle, fuel)
 | 
			
		||||
    if not DoesEntityExist(vehicle) then return end
 | 
			
		||||
    return exports['ti_fuel']:setFuel(vehicle, fuel, "RON91")
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return Fuel
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,30 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
local resourceName = "x-fuel"
 | 
			
		||||
if GetResourceState(resourceName) == 'missing' then return end
 | 
			
		||||
Fuel = Fuel or {}
 | 
			
		||||
 | 
			
		||||
---This will get the name of the Fuel being used (if a supported Fuel).
 | 
			
		||||
---@return string
 | 
			
		||||
Fuel.GetResourceName = function()
 | 
			
		||||
    return resourceName
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will get the fuel level of the vehicle.
 | 
			
		||||
---@param vehicle number The vehicle entity ID.
 | 
			
		||||
---@return number fuel The fuel level of the vehicle.
 | 
			
		||||
Fuel.GetFuel = function(vehicle)
 | 
			
		||||
    if not DoesEntityExist(vehicle) then return 0.0 end
 | 
			
		||||
    local level, _ = exports["x-fuel"]:getFuel(vehicle)
 | 
			
		||||
    return level
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will set the fuel level of the vehicle.
 | 
			
		||||
---@param vehicle number The vehicle entity ID.
 | 
			
		||||
---@param fuel number The fuel level to set.
 | 
			
		||||
---@return nil
 | 
			
		||||
Fuel.SetFuel = function(vehicle, fuel)
 | 
			
		||||
    if not DoesEntityExist(vehicle) then return end
 | 
			
		||||
    return exports['x-fuel']:SetFuel(vehicle, fuel)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return Fuel
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,26 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
HelpText = HelpText or {}
 | 
			
		||||
 | 
			
		||||
---This will show a help text message at the screen position passed
 | 
			
		||||
---@param message string
 | 
			
		||||
---@param _position string
 | 
			
		||||
---@return nil
 | 
			
		||||
HelpText.ShowHelpText = function(message, _position)
 | 
			
		||||
    return Framework.ShowHelpText(message, _position)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will hide the help text message on the screen
 | 
			
		||||
---@return nil
 | 
			
		||||
HelpText.HideHelpText = function()
 | 
			
		||||
    return Framework.HideHelpText()
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
RegisterNetEvent('community_bridge:Client:ShowHelpText', function(message, position)
 | 
			
		||||
    HelpText.ShowHelpText(message, position)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
RegisterNetEvent('community_bridge:Client:HideHelpText', function()
 | 
			
		||||
    HelpText.HideHelpText()
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
return HelpText
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,18 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
HelpText = HelpText or {}
 | 
			
		||||
 | 
			
		||||
---This will show a help text message to the specified player at the screen position passed
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param message string
 | 
			
		||||
---@param position string
 | 
			
		||||
HelpText.ShowHelpText = function(src, message, position)
 | 
			
		||||
    TriggerClientEvent('community_bridge:Client:ShowHelpText', src, message, position)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will hide the help text message on the screen for the specified player
 | 
			
		||||
---@param src number
 | 
			
		||||
HelpText.HideHelpText = function(src)
 | 
			
		||||
    TriggerClientEvent('community_bridge:Client:HideHelpText', src)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return HelpText
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,22 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
HelpText = HelpText or {}
 | 
			
		||||
local resourceName = "cd_drawtextui"
 | 
			
		||||
local configValue = BridgeSharedConfig.HelpText
 | 
			
		||||
if (configValue == "auto" and GetResourceState(resourceName) ~= "started") or (configValue ~= "auto" and configValue ~= resourceName) then return end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
---This will show a help text message at the screen position passed
 | 
			
		||||
---@param message string
 | 
			
		||||
---@param _position string
 | 
			
		||||
---@return nil
 | 
			
		||||
HelpText.ShowHelpText = function(message, _position)
 | 
			
		||||
    return TriggerEvent('cd_drawtextui:ShowUI', 'show', message)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will hide the help text message on the screen
 | 
			
		||||
---@return nil
 | 
			
		||||
HelpText.HideHelpText = function()
 | 
			
		||||
    return TriggerEvent('cd_drawtextui:HideUI')
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return HelpText
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,21 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
HelpText = HelpText or {}
 | 
			
		||||
local resourceName = "jg-textui"
 | 
			
		||||
local configValue = BridgeSharedConfig.HelpText
 | 
			
		||||
if (configValue == "auto" and GetResourceState(resourceName) ~= "started") or (configValue ~= "auto" and configValue ~= resourceName) then return end
 | 
			
		||||
 | 
			
		||||
---This will show a help text message at the screen position passed
 | 
			
		||||
---@param message string
 | 
			
		||||
---@param _position string
 | 
			
		||||
---@return nil
 | 
			
		||||
HelpText.ShowHelpText = function(message, _position)
 | 
			
		||||
    return exports['jg-textui']:DrawText(message)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will hide the help text message on the screen
 | 
			
		||||
---@return nil
 | 
			
		||||
HelpText.HideHelpText = function()
 | 
			
		||||
    return exports['jg-textui']:HideText()
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return HelpText
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,21 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
HelpText = HelpText or {}
 | 
			
		||||
local resourceName = "lab-HintUI"
 | 
			
		||||
local configValue = BridgeSharedConfig.HelpText
 | 
			
		||||
if (configValue == "auto" and GetResourceState(resourceName) ~= "started") or (configValue ~= "auto" and configValue ~= resourceName) then return end
 | 
			
		||||
 | 
			
		||||
---This will show a help text message at the screen position passed
 | 
			
		||||
---@param message string
 | 
			
		||||
---@param _position string
 | 
			
		||||
---@return nil
 | 
			
		||||
HelpText.ShowHelpText = function(message, _position)
 | 
			
		||||
    return exports['lab-HintUI']:Show(message, "Hint Text")
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will hide the help text message on the screen
 | 
			
		||||
---@return nil
 | 
			
		||||
HelpText.HideHelpText = function()
 | 
			
		||||
    return exports['lab-HintUI']:Hide()
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return HelpText
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,21 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
HelpText = HelpText or {}
 | 
			
		||||
local resourceName = "lation_ui"
 | 
			
		||||
local configValue = BridgeSharedConfig.HelpText
 | 
			
		||||
if (configValue == "auto" and GetResourceState(resourceName) ~= "started") or (configValue ~= "auto" and configValue ~= resourceName) then return end
 | 
			
		||||
 | 
			
		||||
---This will show a help text message at the screen position passed
 | 
			
		||||
---@param message string
 | 
			
		||||
---@param position string
 | 
			
		||||
---@return nil
 | 
			
		||||
HelpText.ShowHelpText = function(message, position)
 | 
			
		||||
    return exports.lation_ui:showText({description = tostring(message), position = position or 'right-center'})
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will hide the help text message on the screen
 | 
			
		||||
---@return nil
 | 
			
		||||
HelpText.HideHelpText = function()
 | 
			
		||||
    return exports.lation_ui:hideText()
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return HelpText
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,21 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
HelpText = HelpText or {}
 | 
			
		||||
local resourceName = "okokTextUI"
 | 
			
		||||
local configValue = BridgeSharedConfig.HelpText
 | 
			
		||||
if (configValue == "auto" and GetResourceState(resourceName) ~= "started") or (configValue ~= "auto" and configValue ~= resourceName) then return end
 | 
			
		||||
 | 
			
		||||
---This will show a help text message at the screen position passed
 | 
			
		||||
---@param message string
 | 
			
		||||
---@param _position string
 | 
			
		||||
---@return nil
 | 
			
		||||
HelpText.ShowHelpText = function(message, _position)
 | 
			
		||||
    return exports['okokTextUI']:Open(message, 'darkblue', _position, false)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will hide the help text message on the screen
 | 
			
		||||
---@return nil
 | 
			
		||||
HelpText.HideHelpText = function()
 | 
			
		||||
    return exports['okokTextUI']:Close()
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return HelpText
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,23 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
HelpText = HelpText or {}
 | 
			
		||||
local resourceName = "ox_lib"
 | 
			
		||||
local configValue = BridgeSharedConfig.HelpText
 | 
			
		||||
if (configValue == "auto" and GetResourceState(resourceName) ~= "started") or (configValue ~= "auto" and configValue ~= resourceName) then return end
 | 
			
		||||
 | 
			
		||||
---This will show a help text message at the screen position passed
 | 
			
		||||
---@param message string
 | 
			
		||||
---@param position string
 | 
			
		||||
---@return nil
 | 
			
		||||
HelpText.ShowHelpText = function(message, position)
 | 
			
		||||
    return exports.ox_lib:showTextUI(message, {
 | 
			
		||||
        position = position or 'right-center'
 | 
			
		||||
    })
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
---This will hide the help text message on the screen
 | 
			
		||||
---@return nil
 | 
			
		||||
HelpText.HideHelpText = function()
 | 
			
		||||
    return exports.ox_lib:hideTextUI()
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return HelpText
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,3 @@
 | 
			
		|||
Housing = Housing or {}
 | 
			
		||||
 | 
			
		||||
return Housing
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,14 @@
 | 
			
		|||
Housing = Housing or {}
 | 
			
		||||
 | 
			
		||||
---This is an internal event, listen for 'community_bridge:Client:OnPlayerInside' instead.
 | 
			
		||||
---This event is triggered when a player enters or leaves a property.
 | 
			
		||||
---@param src number
 | 
			
		||||
---@param insideId string
 | 
			
		||||
RegisterNetEvent('community_bridge:Server:_OnPlayerInside', function(src, insideId)
 | 
			
		||||
    local currentBucket = GetPlayerRoutingBucket(src)
 | 
			
		||||
    local playerEntity = GetPlayerPed(src)
 | 
			
		||||
    local playerCoords = GetEntityCoords(playerEntity)
 | 
			
		||||
    TriggerEvent('community_bridge:Client:OnPlayerInside', src, insideId, currentBucket, playerCoords)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
return Housing
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,13 @@
 | 
			
		|||
if GetResourceState('bcs-housing') == 'missing' then return end
 | 
			
		||||
 | 
			
		||||
Housing = Housing or {}
 | 
			
		||||
 | 
			
		||||
RegisterNetEvent('Housing:client:EnterHome', function(insideId)
 | 
			
		||||
    TriggerServerEvent('community_bridge:Server:_OnPlayerInside', insideId)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
RegisterNetEvent("Housing:client:DeleteFurnitures", function()
 | 
			
		||||
    TriggerServerEvent('community_bridge:Server:_OnPlayerInside', false)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
return Housing
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,5 @@
 | 
			
		|||
if GetResourceState('bcs-housing') == 'missing' then return end
 | 
			
		||||
 | 
			
		||||
Housing = Housing or {}
 | 
			
		||||
 | 
			
		||||
return Housing
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,5 @@
 | 
			
		|||
if GetResourceState('esx_property') == 'missing' then return end
 | 
			
		||||
 | 
			
		||||
Housing = Housing or {}
 | 
			
		||||
 | 
			
		||||
return Housing
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,15 @@
 | 
			
		|||
if GetResourceState('esx_property') == 'missing' then return end
 | 
			
		||||
 | 
			
		||||
Housing = Housing or {}
 | 
			
		||||
 | 
			
		||||
RegisterNetEvent('esx_property:enter', function(insideId)
 | 
			
		||||
    local src = source
 | 
			
		||||
    TriggerEvent('community_bridge:Server:_OnPlayerInside', src, insideId)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
RegisterNetEvent('esx_property:leave', function(insideId)
 | 
			
		||||
    local src = source
 | 
			
		||||
    TriggerEvent('community_bridge:Server:_OnPlayerInside', src, insideId)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
return Housing
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,5 @@
 | 
			
		|||
if GetResourceState('ps-housing') == 'missing' then return end
 | 
			
		||||
 | 
			
		||||
Housing = Housing or {}
 | 
			
		||||
 | 
			
		||||
return Housing
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,15 @@
 | 
			
		|||
if GetResourceState('ps-housing') == 'missing' then return end
 | 
			
		||||
 | 
			
		||||
Housing = Housing or {}
 | 
			
		||||
 | 
			
		||||
RegisterNetEvent('ps-housing:server:enterProperty', function(insideId)
 | 
			
		||||
    local src = source
 | 
			
		||||
    TriggerEvent('community_bridge:Server:_OnPlayerInside', src, insideId)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
RegisterNetEvent('ps-housing:server:leaveProperty', function(insideId)
 | 
			
		||||
    local src = source
 | 
			
		||||
    TriggerEvent('community_bridge:Server:_OnPlayerInside', src, insideId)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
return Housing
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,5 @@
 | 
			
		|||
if GetResourceState('qb-appartments') == 'missing' then return end
 | 
			
		||||
 | 
			
		||||
Housing = Housing or {}
 | 
			
		||||
 | 
			
		||||
return Housing
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,11 @@
 | 
			
		|||
if GetResourceState('qb-appartments') == 'missing' then return end
 | 
			
		||||
 | 
			
		||||
Housing = Housing or {}
 | 
			
		||||
 | 
			
		||||
RegisterNetEvent('qb-apartments:server:SetInsideMeta', function(house, insideId, bool, isVisiting)
 | 
			
		||||
    local src = source
 | 
			
		||||
    insideId = bool and house .. '-' .. insideId or nil
 | 
			
		||||
    TriggerEvent('community_bridge:Server:_OnPlayerInside', src, insideId)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
return Housing
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,5 @@
 | 
			
		|||
if GetResourceState('qb-houses') == 'missing' then return end
 | 
			
		||||
 | 
			
		||||
Housing = Housing or {}
 | 
			
		||||
 | 
			
		||||
return Housing
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,11 @@
 | 
			
		|||
if GetResourceState('qb-houses') == 'missing' then return end
 | 
			
		||||
 | 
			
		||||
Housing = Housing or {}
 | 
			
		||||
 | 
			
		||||
RegisterNetEvent('qb-houses:server:SetInsideMeta', function(insideId, bool)
 | 
			
		||||
    local src = source
 | 
			
		||||
    insideId = bool and insideId or nil
 | 
			
		||||
    TriggerEvent('community_bridge:Server:_OnPlayerInside', src, insideId)
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
return Housing
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,99 @@
 | 
			
		|||
function QBTypeToOxType(_type)
 | 
			
		||||
    if _type == "text" then
 | 
			
		||||
        return "input"
 | 
			
		||||
    elseif _type == "password" then
 | 
			
		||||
        return "input"
 | 
			
		||||
    elseif _type == "number" then
 | 
			
		||||
        return "number"
 | 
			
		||||
    elseif _type == "radio" then
 | 
			
		||||
        return "checkbox"
 | 
			
		||||
    elseif _type == "checkbox" then
 | 
			
		||||
        return "checkbox"
 | 
			
		||||
    elseif _type == "select" then
 | 
			
		||||
        return "select"
 | 
			
		||||
    end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function QBToOxInput(data)
 | 
			
		||||
    local returnData = {}
 | 
			
		||||
    for i, v in pairs(data) do
 | 
			
		||||
        local input = {
 | 
			
		||||
            label = v.text,
 | 
			
		||||
            name = i,
 | 
			
		||||
            type = QBTypeToOxType(v.type),
 | 
			
		||||
            required = v.isRequired,
 | 
			
		||||
            default = v.placeholder,
 | 
			
		||||
        }
 | 
			
		||||
        if v.type == "select" then
 | 
			
		||||
            input.options = {}
 | 
			
		||||
            for i, v in pairs(v.options) do
 | 
			
		||||
                table.insert(input.options, {value = v.value, label = v.text})
 | 
			
		||||
            end
 | 
			
		||||
        elseif v.type == "checkbox" then
 | 
			
		||||
            for i, v in pairs(v.options) do
 | 
			
		||||
                table.insert(returnData, {value = v.value, label = v.text})
 | 
			
		||||
            end
 | 
			
		||||
        end
 | 
			
		||||
        table.insert(returnData, input)
 | 
			
		||||
    end
 | 
			
		||||
    return returnData
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function OxTypeToQBType(_type)
 | 
			
		||||
    if _type == "input" then
 | 
			
		||||
        return "text"
 | 
			
		||||
    elseif _type == "number" then
 | 
			
		||||
        return "number"
 | 
			
		||||
    elseif _type == "checkbox" then
 | 
			
		||||
        return "checkbox"
 | 
			
		||||
    elseif _type == "select" then
 | 
			
		||||
        return "select"
 | 
			
		||||
    elseif _type == "multi-select" then
 | 
			
		||||
        return "select"
 | 
			
		||||
    elseif _type == "slider" then
 | 
			
		||||
        return "number"
 | 
			
		||||
    elseif _type == "color" then
 | 
			
		||||
        return "text"
 | 
			
		||||
    elseif _type == "date" then
 | 
			
		||||
        return "date"
 | 
			
		||||
    elseif _type == "date-range" then
 | 
			
		||||
        return "date"
 | 
			
		||||
    elseif _type == "time" then
 | 
			
		||||
        return "time"
 | 
			
		||||
    elseif _type == "textarea" then
 | 
			
		||||
        return "text"
 | 
			
		||||
    end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function OxToQBInput(data)
 | 
			
		||||
    local returnData = {}
 | 
			
		||||
    for i, v in pairs(data) do
 | 
			
		||||
        local input = {
 | 
			
		||||
            text = v.label,
 | 
			
		||||
            name = i,
 | 
			
		||||
            type = OxTypeToQBType(v.type),
 | 
			
		||||
            isRequired = v.required,
 | 
			
		||||
            default = v.default or "",
 | 
			
		||||
        }
 | 
			
		||||
        if v.type == "select" then
 | 
			
		||||
            input.text = ""
 | 
			
		||||
            input.options = {}
 | 
			
		||||
            for k, j in pairs(v.options) do
 | 
			
		||||
                table.insert(input.options, {value = j.value, text = j.label})
 | 
			
		||||
            end
 | 
			
		||||
        elseif v.type == "checkbox" then
 | 
			
		||||
            input.text = ""
 | 
			
		||||
            input.options = {}
 | 
			
		||||
            if v.options then -- Checks if options varible is valid so checkboxes are bundled together (not used by ox for each checkpoint)
 | 
			
		||||
                for k, j in pairs(v.options) do
 | 
			
		||||
                    table.insert(input.options, {value = j.value, text = j.label, checked = j.checked}) -- added checked option (used to show box as ticked or not)
 | 
			
		||||
                end
 | 
			
		||||
            else -- If options is not valid or people pass a single checkbox then it will be a single checkbox per entry
 | 
			
		||||
                table.insert(input.options, {value = v.value, text = v.label, checked = v.checked}) -- Kept value just incase it's used for other stuffs
 | 
			
		||||
            end
 | 
			
		||||
        end
 | 
			
		||||
        table.insert(returnData, input)
 | 
			
		||||
    end
 | 
			
		||||
    return returnData
 | 
			
		||||
end
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,21 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
local resourceName = "lation_ui"
 | 
			
		||||
local configValue = BridgeClientConfig.InputSystem
 | 
			
		||||
if (configValue == "auto" and GetResourceState(resourceName) == "missing") or (configValue ~= "auto" and configValue ~= resourceName) then return end
 | 
			
		||||
 | 
			
		||||
Input = {}
 | 
			
		||||
 | 
			
		||||
function Input.Open(title, data, isQBFormat, submitText)
 | 
			
		||||
    local inputs = data.inputs
 | 
			
		||||
    if isQBFormat then
 | 
			
		||||
        return exports.lation_ui:input({title = title, inputs = QBToOxInput(inputs)})
 | 
			
		||||
    else
 | 
			
		||||
        return exports.lation_ui:input({title = title, options = data})
 | 
			
		||||
    end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function Input.GetResourceName()
 | 
			
		||||
    return resourceName
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return Input
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,21 @@
 | 
			
		|||
---@diagnostic disable: duplicate-set-field
 | 
			
		||||
local resourceName = "ox_lib"
 | 
			
		||||
local configValue = BridgeClientConfig.InputSystem
 | 
			
		||||
if (configValue == "auto" and GetResourceState(resourceName) == "missing") or (configValue ~= "auto" and configValue ~= resourceName) then return end
 | 
			
		||||
 | 
			
		||||
Input = {}
 | 
			
		||||
 | 
			
		||||
function Input.Open(title, data, isQBFormat, submitText)
 | 
			
		||||
    local inputs = data.inputs
 | 
			
		||||
    if isQBFormat then
 | 
			
		||||
        return lib.inputDialog(title, QBToOxInput(inputs))
 | 
			
		||||
    else
 | 
			
		||||
        return lib.inputDialog(title, data)
 | 
			
		||||
    end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function Input.GetResourceName()
 | 
			
		||||
    return resourceName
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
return Input
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show more
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue