This commit is contained in:
Nordi98 2025-08-06 16:37:06 +02:00
parent 510e3ffcf2
commit f43cf424cf
305 changed files with 34683 additions and 0 deletions

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -0,0 +1,204 @@
---@diagnostic disable: duplicate-set-field
if GetResourceState('esx_skin') == 'missing' then return end
if GetResourceState('rcore_clothing') ~= 'missing' then return end
Clothing = Clothing or {}
-- {"glasses_2":0,"shoes_1":70,"dad":0,"shoes_2":2,"pants_1":28,"eye_squint":0,"ears_1":-1,"hair_color_1":61,"eyebrows_6":0,"bodyb_3":-1,"beard_1":11,"complexion_2":0,"arms_2":0,"hair_1":76,"nose_1":0,"blush_2":0,"bracelets_2":0,"blush_1":0,"jaw_2":0,"helmet_1":-1,"eyebrows_3":0,"watches_1":-1,"eyebrows_4":0,"jaw_1":0,"lipstick_1":0,"eyebrows_1":0,"nose_4":0,"age_2":0,"torso_1":23,"hair_2":0,"chin_2":0,"arms":1,"chain_1":22,"nose_2":0,"cheeks_1":2,"tshirt_1":4,"glasses_1":0,"pants_2":3,"lipstick_4":0,"chin_13":0,"beard_4":0,"beard_3":0,"chain_2":2,"cheeks_3":6,"sex":0,"lipstick_3":0,"makeup_1":0,"hair_color_2":29,"mask_2":0,"chin_1":0,"eyebrows_5":0,"bodyb_2":0,"sun_2":0,"watches_2":0,"sun_1":0,"chin_4":0,"nose_3":0,"helmet_2":0,"bags_2":0,"moles_2":0,"mask_1":0,"blemishes_2":0,"chest_1":0,"cheeks_2":-10,"age_1":0,"chest_2":0,"beard_2":10,"torso_2":2,"blush_3":0,"bproof_1":0,"moles_1":0,"chin_3":0,"lip_thickness":-2,"lipstick_2":0,"chest_3":0,"complexion_1":0,"bodyb_4":0,"neck_thickness":0,"bproof_2":0,"makeup_3":0,"tshirt_2":2,"makeup_2":0,"makeup_4":0,"bracelets_1":-1,"decals_2":0,"nose_6":0,"bodyb_1":-1,"bags_1":0,"blemishes_1":0,"decals_1":0,"mom":21,"eyebrows_2":0,"eye_color":0,"skin_md_weight":50,"face_md_weight":50,"nose_5":10,"ears_2":0}
Components = {}
Components.Map = {
[1] = 'mask', -- componentId
[2] = 'ears',
[3] = 'arms',
[4] = 'pants',
[5] = 'bags',
[6] = 'shoes',
[7] = 'chain',
[8] = 'tshirt',
[9] = 'bproof',
[10] = 'decals',
[11] = 'torso'
}
Components.InverseMap = {
mask = 1, -- componentId
arms = 3,
pants = 4,
bags = 5,
shoes = 6,
chain = 7,
tshirt = 8,
bproof = 9,
decals = 10,
torso = 11,
}
Props = {}
Props.Map = {
[0] = 'helmet', -- propId
[1] = 'glasses',
[2] = 'ears',
[6] = 'watches',
[7] = 'bracelets'
}
Props.InverseMap = {
helmet_1 = 0,
helmet_2 = 0,
glasses_1 = 1,
glasses_2 = 1,
ears_1 = 2,
ears_2 = 2,
watches_1 = 6,
watches_2 = 6,
bracelets_1 = 7,
bracelets_2 = 7,
}
-- Converts from illinium format to esx format
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 .. '_1'] = componentData.drawable
returnComponents[componentId .. '_2'] = componentData.texture
end
end
return returnComponents
end
function Components.ConvertToDefault(esxComponents)
local returnComponents = {}
for componentIndex, componentData in pairs(esxComponents or {}) do
local isTexture = componentIndex:find('_2')
componentIndex = componentIndex:gsub('_1', ''):gsub('_2', '')
local componentId = Components.InverseMap[componentIndex]
if componentId then
if isTexture then
returnComponents[componentId] = returnComponents[componentId] or {}
returnComponents[componentId].texture = componentData
else
returnComponents[componentId] = returnComponents[componentId] or {}
returnComponents[componentId].component_id = componentId
returnComponents[componentId].drawable = componentData
returnComponents[componentId].texture = returnComponents[componentId].texture or 0
end
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 .. '_1'] = propData.drawable
returnProps[propId .. '_2'] = propData.texture
end
end
return returnProps
end
function Props.ConvertToDefault(esxProps)
local returnProps = {}
for propIndex, propData in pairs(esxProps or {}) do
local isTexture = propIndex:find('_2')
propIndex = propIndex:gsub('_1', ''):gsub('_2', '')
local propId = Props.InverseMap[propIndex]
if propId then
if isTexture then
returnProps[propId] = returnProps[propId] or {}
returnProps[propId].texture = propData
else
returnProps[propId] = returnProps[propId] or {}
returnProps[propId].prop_id = propId
returnProps[propId].drawable = propData
returnProps[propId].texture = returnProps[propId].texture or 0
end
end
table.sort(returnProps, function(a, b)
return a.prop_id < b.prop_id
end)
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(esxClothing)
local components = Components.ConvertToDefault(esxClothing)
local props = Props.ConvertToDefault(esxClothing)
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('esx-clothing:client:loadOutfit', repackedTable)
-- end

View file

@ -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

View file

@ -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)

View file

@ -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?

View file

@ -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

View file

@ -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)

View file

@ -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?

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,4 @@
if GetResourceState('bub-mdt') == 'missing' then return end
Dispatch = Dispatch or {}
return Dispatch

View file

@ -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

View file

@ -0,0 +1,4 @@
if GetResourceState('cd_dispatch') == 'missing' then return end
Dispatch = Dispatch or {}
return Dispatch

View file

@ -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

View file

@ -0,0 +1,4 @@
if GetResourceState('kartik-mdt') == 'missing' then return end
Dispatch = Dispatch or {}
return Dispatch

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,4 @@
if GetResourceState('linden_outlawalert') == 'missing' then return end
Dispatch = Dispatch or {}
return Dispatch

View file

@ -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

View file

@ -0,0 +1,4 @@
if GetResourceState('origen_police') == 'missing' then return end
Dispatch = Dispatch or {}
return Dispatch

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,4 @@
if GetResourceState('qs-dispatch') == 'missing' then return end
Dispatch = Dispatch or {}
return Dispatch

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,4 @@
if GetResourceState('tk_dispatch') == 'missing' then return end
Dispatch = Dispatch or {}
return Dispatch

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,3 @@
Framework = Framework or {}
return Framework

View file

@ -0,0 +1,3 @@
Framework = Framework or {}
return Framework

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,3 @@
Housing = Housing or {}
return Housing

View file

@ -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

View file

@ -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

View file

@ -0,0 +1,5 @@
if GetResourceState('bcs-housing') == 'missing' then return end
Housing = Housing or {}
return Housing

View file

@ -0,0 +1,5 @@
if GetResourceState('esx_property') == 'missing' then return end
Housing = Housing or {}
return Housing

View file

@ -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

View file

@ -0,0 +1,5 @@
if GetResourceState('ps-housing') == 'missing' then return end
Housing = Housing or {}
return Housing

View file

@ -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

View file

@ -0,0 +1,5 @@
if GetResourceState('qb-appartments') == 'missing' then return end
Housing = Housing or {}
return Housing

View file

@ -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

View file

@ -0,0 +1,5 @@
if GetResourceState('qb-houses') == 'missing' then return end
Housing = Housing or {}
return Housing

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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