diff --git a/modules/clothing/esx_skin/client.lua b/modules/clothing/esx_skin/client.lua new file mode 100644 index 0000000..da941c3 --- /dev/null +++ b/modules/clothing/esx_skin/client.lua @@ -0,0 +1,148 @@ +if GetResourceState('esx_skin') ~= 'started' then return end + +Clothing = {} + +StoredOldClothing = {} + +RegisterNetEvent('community_bridge:client:updateStoredClothing', function(skindata) + StoredOldClothing = skindata +end) + +local clothingData = { + male = { + components = { + face = {component_id = 0, texture = 0, drawable = 2}, + mask = {component_id = 1, texture = 0, drawable = 2}, + hair = {component_id = 2, texture = 0, drawable = 2}, + arms = {component_id = 3, texture = 0, drawable = 2}, + pants = {component_id = 4, texture = 0, drawable = 22}, + bag = {component_id = 5, texture = 1, drawable = 33}, + shoes = {component_id = 6, texture = 1, drawable = 33}, + accessory = {component_id = 7, texture = 1, drawable = 33}, + shirt = {component_id = 8, texture = 1, drawable = 11}, + bodyarmor = {component_id = 9, texture = 1, drawable = 33}, + decals = {component_id = 10, texture = 1, drawable = 33}, + jacket = {component_id = 11, texture = 2, drawable = 4}, + }, + props = { + hats = {prop_id = 0, texture = 2, drawable = 4}, + glasses = {prop_id = 1, texture = 2, drawable = 4}, + ears = {prop_id = 2, texture = 2, drawable = 4}, + watches = {prop_id = 6, texture = 2, drawable = 4}, + bracelets = {prop_id = 7, texture = 2, drawable = 4}, + } + }, + female = { + components = { + face = {component_id = 0, texture = 0, drawable = 2}, + mask = {component_id = 1, texture = 0, drawable = 2}, + hair = {component_id = 2, texture = 0, drawable = 2}, + arms = {component_id = 3, texture = 0, drawable = 2}, + pants = {component_id = 4, texture = 0, drawable = 22}, + bag = {component_id = 5, texture = 1, drawable = 33}, + shoes = {component_id = 6, texture = 1, drawable = 33}, + accessory = {component_id = 7, texture = 1, drawable = 33}, + shirt = {component_id = 8, texture = 1, drawable = 11}, + bodyarmor = {component_id = 9, texture = 1, drawable = 33}, + decals = {component_id = 10, texture = 1, drawable = 33}, + jacket = {component_id = 11, texture = 2, drawable = 4}, + }, + props = { + hats = {prop_id = 0, texture = 2, drawable = 4}, + glasses = {prop_id = 1, texture = 2, drawable = 4}, + ears = {prop_id = 2, texture = 2, drawable = 4}, + watches = {prop_id = 6, texture = 2, drawable = 4}, + bracelets = {prop_id = 7, texture = 2, drawable = 4}, + } + }, +} + +local function convertDataToFormat(characterData) + local gender = characterData.sex + + local repackedClothingData = { + [gender] = { + components = {}, + props = {} + } + } + + local componentMap = { + tshirt_1 = 8, -- shirt + torso_1 = 11, -- jacket + decals_1 = 10, -- decals + arms = 3, -- arms + pants_1 = 4, -- pants + shoes_1 = 6, -- shoes + mask_1 = 1, -- mask + bproof_1 = 9, -- body armor + chain_1 = 7, -- accessory (could be a necklace) + bags_1 = 5, -- bag + } + + for componentName, componentId in pairs(componentMap) do + if characterData[componentName] then + repackedClothingData[gender].components[componentName] = { + component_id = componentId, + texture = characterData[componentName.."_2"], + drawable = characterData[componentName.."_1"], + } + end + end + + local propMap = { + {"helmet_1", 0}, -- helmet + {"glasses_1", 1}, -- glasses + {"ears_1", 2}, -- ears + {"watches_1", 6}, -- watches + {"bracelets_1", 7} -- bracelets + } + + for _, prop in ipairs(propMap) do + local propName = prop[1] + local propId = prop[2] + + if characterData[propName] then + repackedClothingData[gender].props[propName] = { + prop_id = propId, + texture = characterData[propName.."_2"], + drawable = characterData[propName.."_1"], + } + end + end + return repackedClothingData +end + +Clothing.SetAppearance = function(clothingData) + if GetEntityModel(cache.ped) == `mp_m_freemode_01` then + clothingData = clothingData.male + clothingData.sex = 0 + else + clothingData = clothingData.female + clothingData.sex = 1 + end + local repackedClothingData = convertDataToFormat(clothingData) + StoredOldClothing = Clothing.GetAppearance + TriggerEvent('skinchanger:loadSkin', repackedClothingData) + return true +end + +Clothing.GetAppearance = function() + ESX.TriggerServerCallback('esx_skin:getPlayerSkin', function(skin) + StoredOldClothing = skin + end) + return true +end + +Clothing.RestoreAppearance = function() + ESX.TriggerServerCallback('esx_skin:getPlayerSkin', function(skin) + TriggerEvent('skinchanger:loadSkin', skin) + end) + return true +end + +Clothing.ReloadSkin = function() + local tableCheck = Table.TableContains(StoredOldClothing, "sex") + if not tableCheck then return Clothing.RestoreAppearance() end + return TriggerEvent('skinchanger:loadSkin', StoredOldClothing) +end \ No newline at end of file diff --git a/modules/clothing/esx_skin/server.lua b/modules/clothing/esx_skin/server.lua new file mode 100644 index 0000000..d0330af --- /dev/null +++ b/modules/clothing/esx_skin/server.lua @@ -0,0 +1,6 @@ +if GetResourceState('esx_skin') ~= 'started' then return end + +RegisterNetEvent("esx_skin:save", function(skin) + local src = source + TriggerClientEvent('community_bridge:client:updateStoredClothing', src, skin) +end) \ No newline at end of file diff --git a/modules/clothing/fivem-appearance/client.lua b/modules/clothing/fivem-appearance/client.lua new file mode 100644 index 0000000..5c998e7 --- /dev/null +++ b/modules/clothing/fivem-appearance/client.lua @@ -0,0 +1,28 @@ +if GetResourceState('fivem-appearance') ~= 'started' then return end + +Clothing = {} + +StoredOldClothing = {} + +Clothing.SetAppearance = function(clothingData) + if GetEntityModel(cache.ped) == `mp_m_freemode_01` then + clothingData = clothingData.male + else + clothingData = clothingData.female + end + StoredOldClothing = exports['fivem-appearance']:getPedAppearance(cache.ped) + exports['fivem-appearance']:setPedAppearance(cache.ped, clothingData) + return true +end + +Clothing.GetAppearance = function() + return exports['fivem-appearance']:getPedAppearance(cache.ped) +end + +Clothing.RestoreAppearance = function() + return exports['fivem-appearance']:setPedAppearance(cache.ped, StoredOldClothing) +end + +Clothing.ReloadSkin = function() + TriggerEvent("fivem-appearance:client:reloadSkin", true) +end \ No newline at end of file diff --git a/modules/clothing/illenium-appearance/client.lua b/modules/clothing/illenium-appearance/client.lua new file mode 100644 index 0000000..ee3c32e --- /dev/null +++ b/modules/clothing/illenium-appearance/client.lua @@ -0,0 +1,45 @@ +if GetResourceState('illenium-appearance') ~= 'started' then return end + +Clothing = {} + +StoredOldClothing = {} + +Clothing.SetAppearance = function(clothingData) + local clothing = {} + if GetEntityModel(cache.ped) == `mp_m_freemode_01` then + clothingData = clothingData.male + else + clothingData = clothingData.female + end + clothing.components = exports['illenium-appearance']:getPedComponents(cache.ped) + clothing.props = exports['illenium-appearance']:getPedProps(cache.ped) + + Prints.Debug(json.encode(clothingData, {indent = true})) + StoredOldClothing = clothing + exports['illenium-appearance']:setPedComponents(cache.ped, clothingData.components) + exports['illenium-appearance']:setPedProp(cache.ped, clothingData.props) + return true +end + +Clothing.GetAppearance = function() + local clothing = {} + if GetEntityModel(cache.ped) == `mp_m_freemode_01` then + clothing = clothing.male + else + clothing = clothing.female + end + clothing.components = exports['illenium-appearance']:getPedComponents(cache.ped) + clothing.props = exports['illenium-appearance']:getPedProps(cache.ped) + + return clothing +end + +Clothing.RestoreAppearance = function() + exports['illenium-appearance']:setPedComponents(cache.ped, StoredOldClothing.components) + exports['illenium-appearance']:setPedProp(cache.ped, StoredOldClothing.props) + return true +end + +Clothing.ReloadSkin = function() + TriggerEvent("illenium-appearance:client:reloadSkin", true) +end diff --git a/modules/clothing/qb-clothing/client.lua b/modules/clothing/qb-clothing/client.lua new file mode 100644 index 0000000..0245f28 --- /dev/null +++ b/modules/clothing/qb-clothing/client.lua @@ -0,0 +1,80 @@ +if GetResourceState('qb-clothing') ~= 'started' then return end + +Clothing = {} + +StoredOldClothing = {} + +RegisterNetEvent('community_bridge:client:updateStoredClothing', function(skindata) + StoredOldClothing = skindata +end) + +Clothing.SetAppearance = function(clothingData) + if GetEntityModel(cache.ped) == `mp_m_freemode_01` then + clothingData = clothingData.male + else + clothingData = clothingData.female + end + local repackedTable = {} + StoredOldClothing = Clothing.GetAppearance + 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) + return true +end + +Clothing.GetAppearance = function() + StoredOldClothing = Utility.GetEntitySkinData(cache.ped) + return Utility.GetEntitySkinData(cache.ped) +end + +Clothing.RestoreAppearance = function() + return Utility.SetEntitySkinData(cache.ped, StoredOldClothing) +end + +Clothing.ReloadSkin = function() + return exports['qb-clothing']:reloadSkin(GetEntityHealth(cache.ped)) +end \ No newline at end of file diff --git a/modules/clothing/qb-clothing/server.lua b/modules/clothing/qb-clothing/server.lua new file mode 100644 index 0000000..d7a283a --- /dev/null +++ b/modules/clothing/qb-clothing/server.lua @@ -0,0 +1,8 @@ +if GetResourceState('qb-clothing') ~= 'started' then return end + +RegisterServerEvent('qb-clothing:saveSkin', function(model, skin) + local src = source + if model ~= nil and skin ~= nil then + TriggerClientEvent('community_bridge:client:updateStoredClothing', src, skin) + end +end) \ No newline at end of file diff --git a/modules/dispatch/cd_dispatch/client.lua b/modules/dispatch/cd_dispatch/client.lua new file mode 100644 index 0000000..4547a3d --- /dev/null +++ b/modules/dispatch/cd_dispatch/client.lua @@ -0,0 +1,18 @@ +if GetResourceState('cd_dispatch') ~= 'started' then return end + +Dispatch = {} + +Dispatch.SendAlert = function(data) + local playerData = exports['cd_dispatch']:GetPlayerInfo() + local randomID = Utility.CreateUniqueId(nil, 14, nil) + TriggerServerEvent('cd_dispatch:AddNotification', { + job_table = data.job, + coords = data.coords or playerData.coords, + title = data.code or '10-80', + message = data.message, + flash = 0, + unique_id = randomID, + sound = 1, + blip = { sprite = 431, scale = 1.2, colour = 3, flashes = false, text = data.message, time = 10000, radius = 0, } + }) +end \ No newline at end of file diff --git a/modules/dispatch/linden_outlawalert/client.lua b/modules/dispatch/linden_outlawalert/client.lua new file mode 100644 index 0000000..4007d99 --- /dev/null +++ b/modules/dispatch/linden_outlawalert/client.lua @@ -0,0 +1,21 @@ +if GetResourceState('linden_outlawalert') ~= 'started' then return end + +Dispatch = {} + +Dispatch.SendAlert = function(data) + local formattedData = { + displayCode = data.code or '10-80', + description = data.message, + isImportant = data.priority or 0, + recipientList = data.job, + length = '10000', + infoM = data.icon or 'fas fa-question', + info = data.message + } + local dispatchData = { + dispatchData = formattedData, + caller = 'Anonymous', + coords = GetEntityCoords(cache.ped) + } + TriggerServerEvent('wf-alerts:svNotify', dispatchData) +end \ No newline at end of file diff --git a/modules/dispatch/ps-dispatch/client.lua b/modules/dispatch/ps-dispatch/client.lua new file mode 100644 index 0000000..69dad7a --- /dev/null +++ b/modules/dispatch/ps-dispatch/client.lua @@ -0,0 +1,75 @@ +if GetResourceState('ps-dispatch') ~= 'started' then return end + +Dispatch = {} + +Dispatch.SendAlert = function(data) + local customData = { + message = data.message, + code = data.code or '10-80', + icon = data.icon or 'fas fa-question', + priority = data.priority or 2, + coords = data.coords or vec3(0.0, 0.0, 0.0), + gender = data.gender or nil, + camId = data.camId or nil, + color = data.firstColor or nil, + callsign = data.callsign or nil, + name = data.name or nil, + vehicle = data.model or nil, + plate = data.plate or nil, + alertTime = data.alertTime or nil, + doorCount = data.doorCount or nil, + automaticGunfire = data.automaticGunfire or false, + alert = { + radius = data.radius or 0, + recipientList = data.job or { 'leo' }, + sprite = data.sprite or 1, + color = data.color or 1, + scale = data.scale or 0.5, + length = data.length or 2, + sound = data.sound or "Lose_1st", + sound2 = data.sound2 or "GTAO_FM_Events_Soundset", + offset = data.offset or false, + flash = data.flash or false + }, + jobs = { data.job or 'leo' } + } + exports["ps-dispatch"]:CustomAlert(customData) +end + +--[[ +-- tested, it worked +CreateThread(function() + local data = { + message = "Fart", + code = '10-80', + icon = 'fas fa-question', + priority = 2, + coords = vec3(0.0, 0.0, 0.0), + gender = nil, + camId = nil, + color = nil, + callsign = nil, + name = "Test Name", + vehicle = nil, + plate = nil, + alertTime = 30000, + doorCount = nil, + automaticGunfire = false, + alert = { + radius = 0, + recipientList = { 'leo' }, + sprite = 1, + color = 1, + scale = 0.5, + length = 2, + sound = "Lose_1st", + sound2 = "GTAO_FM_Events_Soundset", + offset = false, + flash = false + }, + jobs = { 'leo' } + } + Dispatch.SendAlert(data) + Prints.Debug("Dispatched") +end) +--]] \ No newline at end of file diff --git a/modules/dispatch/rcore_dispatch/client.lua b/modules/dispatch/rcore_dispatch/client.lua new file mode 100644 index 0000000..358c9c0 --- /dev/null +++ b/modules/dispatch/rcore_dispatch/client.lua @@ -0,0 +1,16 @@ +if GetResourceState('rcore_dispatch') ~= 'started' then return end + +Dispatch = {} + +Dispatch.SendAlert = function(data) + local playerData = exports['rcore_dispatch']:GetPlayerData() + TriggerEvent('rcore_dispatch:server:sendAlert', { + code = data.code or '10-80', + default_priority = 'low', + coords = data.coords or playerData.coords, + job = data.job, + text = data.message or 'No message provided', + type = 'alerts', + blip = { sprite = 54, colour = 3, scale = 0.7, text = data.message or "No Message", flashes = false, radius = 0 } + }) +end \ No newline at end of file diff --git a/modules/doorlock/doors_creator/client.lua b/modules/doorlock/doors_creator/client.lua new file mode 100644 index 0000000..dbf6c86 --- /dev/null +++ b/modules/doorlock/doors_creator/client.lua @@ -0,0 +1,7 @@ +if GetResourceState('doors_creator') ~= 'started' then return end + +Doorlock = Doorlock or {} + +Doorlock.GetClosestDoor = function() + return exports["doors_creator"]:getClosestActiveDoor() +end \ No newline at end of file diff --git a/modules/doorlock/doors_creator/server.lua b/modules/doorlock/doors_creator/server.lua new file mode 100644 index 0000000..0aee303 --- /dev/null +++ b/modules/doorlock/doors_creator/server.lua @@ -0,0 +1,13 @@ +if GetResourceState('doors_creator') ~= 'started' then return end + +Doorlock = Doorlock or {} + +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 \ No newline at end of file diff --git a/modules/doorlock/ox_doorlock/client.lua b/modules/doorlock/ox_doorlock/client.lua new file mode 100644 index 0000000..b2dd1aa --- /dev/null +++ b/modules/doorlock/ox_doorlock/client.lua @@ -0,0 +1,7 @@ +if GetResourceState('ox_doorlock') ~= 'started' then return end + +Doorlock = Doorlock or {} + +Doorlock.GetClosestDoor = function() + return exports.ox_doorlock:getClosestDoor() +end diff --git a/modules/doorlock/ox_doorlock/server.lua b/modules/doorlock/ox_doorlock/server.lua new file mode 100644 index 0000000..1594980 --- /dev/null +++ b/modules/doorlock/ox_doorlock/server.lua @@ -0,0 +1,13 @@ +if GetResourceState('ox_doorlock') ~= 'started' then return end + +Doorlock = Doorlock or {} + +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 \ No newline at end of file diff --git a/modules/doorlock/qb-doorlock/client.lua b/modules/doorlock/qb-doorlock/client.lua new file mode 100644 index 0000000..ba8166e --- /dev/null +++ b/modules/doorlock/qb-doorlock/client.lua @@ -0,0 +1,20 @@ +if GetResourceState('qb-doorlock') ~= 'started' then return end + +Doorlock = Doorlock or {} + +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 \ No newline at end of file diff --git a/modules/doorlock/qb-doorlock/server.lua b/modules/doorlock/qb-doorlock/server.lua new file mode 100644 index 0000000..3a48b0c --- /dev/null +++ b/modules/doorlock/qb-doorlock/server.lua @@ -0,0 +1,8 @@ +if GetResourceState('qb-doorlock') ~= 'started' then return end + +Doorlock = Doorlock or {} + +Doorlock.ToggleDoorLock = function(doorID, toggle) + TriggerClientEvent('qb-doorlock:client:setState', -1, 0, doorID, toggle, false, false, false) + return true +end \ No newline at end of file diff --git a/modules/doorlock/rcore_doorlock/client.lua b/modules/doorlock/rcore_doorlock/client.lua new file mode 100644 index 0000000..041307f --- /dev/null +++ b/modules/doorlock/rcore_doorlock/client.lua @@ -0,0 +1,18 @@ +if GetResourceState('rcore_doorlock') ~= 'started' then return end + +Doorlock = Doorlock or {} + +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 \ No newline at end of file diff --git a/modules/doorlock/rcore_doorlock/server.lua b/modules/doorlock/rcore_doorlock/server.lua new file mode 100644 index 0000000..1af685e --- /dev/null +++ b/modules/doorlock/rcore_doorlock/server.lua @@ -0,0 +1,13 @@ +if GetResourceState('rcore_doorlock') ~= 'started' then return end + +Doorlock = Doorlock or {} + +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 \ No newline at end of file diff --git a/modules/framework/es_extended/client.lua b/modules/framework/es_extended/client.lua new file mode 100644 index 0000000..0a4d2c9 --- /dev/null +++ b/modules/framework/es_extended/client.lua @@ -0,0 +1,54 @@ +if GetResourceState('es_extended') ~= 'started' then return end + +ESX = exports["es_extended"]:getSharedObject() + +Framework = {} + +Framework.GetPlayerData = function() + return ESX.PlayerData +end + +Framework.GetPlayerMetaData = function(metadata) + return ESX.GetPlayerData().metadata[metadata] +end + +Framework.GetPlayerIdentifier = function() + return ESX.GetPlayerData().identifier +end + +Framework.GetPlayerName = function() + local playerData = ESX.GetPlayerData() + return playerData.firstName, playerData.lastName +end + +Framework.GetPlayerJob = function() + local playerData = ESX.GetPlayerData() + return playerData.job.name, playerData.job.label, playerData.job.grade_label, playerData.job.grade +end + +Framework.GetPlayerInventory = function() + return ESX.GetPlayerData().inventory +end + +Framework.GetIsPlayerDead = function() + return ESX.GetPlayerData().dead +end + +RegisterNetEvent('esx:playerLoaded', function(xPlayer) + Wait(1500) + FillBridgeTables() + TriggerEvent('community_bridge:Client:OnPlayerLoaded') +end) + +RegisterNetEvent('esx:onPlayerLogout', function() + ClearClientSideVariables() + TriggerEvent('community_bridge:Client:OnPlayerUnload') +end) + +RegisterNetEvent('esx:setJob', function(data) + PlayerJobName = data.name + PlayerJobLabel = data.label + PlayerJobGradeName = data.grade_label + PlayerJobGradeLevel = data.grade + TriggerEvent('community_bridge:Client:OnPlayerJobUpdate',PlayerJobName, PlayerJobLabel, PlayerJobGradeName, PlayerJobGradeLevel) +end) diff --git a/modules/framework/es_extended/server.lua b/modules/framework/es_extended/server.lua new file mode 100644 index 0000000..e8e65d1 --- /dev/null +++ b/modules/framework/es_extended/server.lua @@ -0,0 +1,213 @@ +if GetResourceState('es_extended') ~= 'started' then return end + +ESX = exports["es_extended"]:getSharedObject() + +Framework = {} + +-- Framework.GetPlayerIdentifier(src) +-- Returns the citizen ID of the player. +Framework.GetPlayerIdentifier = function(src) + local xPlayer = ESX.GetPlayerFromId(src) + return xPlayer.getIdentifier() +end + +-- Framework.GetPlayerName(src) +-- Returns the first and last name of the player. +Framework.GetPlayerName = function(src) + local xPlayer = ESX.GetPlayerFromId(src) + return xPlayer.variables.firstName, xPlayer.variables.lastName +end + +-- Framework.GetItem(src, item, metadata) +-- 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} +Framework.GetItem = function(src, item, _) + local playerItems = ESX.GetPlayerFromId(src).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 + +-- Framework.GetItemCount(src, item, _) +-- Returns the count of items matching the specified name and if passed metadata from the player's inventory. +Framework.GetItemCount = function(src, item, _) + local xPlayer = ESX.GetPlayerFromId(src) + return xPlayer.getInventoryItem(item).count +end + +-- Framework.GetPlayerInventory(src) +-- Returns the entire inventory of the player as a table. +-- returns {name = v.name, count = v.amount, _, _} +Framework.GetPlayerInventory = function(src) + local playerItems = ESX.GetPlayerFromId(src).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. +Framework.SetPlayerMetadata = function(src, metadata, value) + local xPlayer = ESX.GetPlayerFromId(src) + xPlayer.setMeta(metadata, value, nil) + return true +end + +-- Framework.GetMetadata(src, metadata) +-- Gets the specified metadata key and value to the player's data. +Framework.GetPlayerMetadata = function(src, metadata) + local xPlayer = ESX.GetPlayerFromId(src) + 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 = ESX.GetPlayerFromId(src) + return xPlayer.get(column) or nil +end + +-- Framework.AddThirst(src, value) +-- Adds the specified value from the player's thirst level. +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. +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 + +Framework.GetHunger = function(src) + local status = Framework.GetStatus(src, "status") + if not status then return 0 end + return status.hunger +end + +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. +Framework.GetPlayerPhone = function(src) + local xPlayer = ESX.GetPlayerFromId(src) + return xPlayer.get("phone_number") +end + +-- Framework.GetPlayerJob(src) +-- Returns the job name, label, grade name, and grade level of the player. +Framework.GetPlayerJob = function(src) + local xPlayer = ESX.GetPlayerFromId(src) + return xPlayer.getJob().name, xPlayer.getJob().label, xPlayer.getJob().grade_label, xPlayer.getJob().grade +end + +-- Framework.GetPlayersByJob(jobname) +-- returns a table of player sources that have the specified job name. +Framework.GetPlayersByJob = function(job) + local players = GetPlayers() + local playerList = {} + for _, src in pairs(players) do + local xPlayer = ESX.GetPlayerFromId(src) + if xPlayer.getJob().name == job then + table.insert(playerList, src) + end + end + return playerList +end + +-- Framework.SetPlayerJob(src, name, grade) +-- Sets the player's job to the specified name and grade. +Framework.SetPlayerJob = function(src, name, grade) + local xPlayer = ESX.GetPlayerFromId(src) + if not ESX.DoesJobExist(name, grade) then lib.print.error("Job Does Not Exsist In Framework :NAME "..name.." Grade:"..grade) return end + return xPlayer.setJob(name, grade, true) +end + +Framework.ToggleDuty = function(src, status) + local xPlayer = ESX.GetPlayerFromId(src) + local name = xPlayer.getJob().name + local grade = xPlayer.getJob().grade + xPlayer.setJob(name, grade, status) +end + +-- Framework.AddAccountBalance(src, _type, amount) +-- Adds the specified amount to the player's account balance of the specified type. +Framework.AddAccountBalance = function(src, _type, amount) + local xPlayer = ESX.GetPlayerFromId(src) + return xPlayer.addAccountMoney(_type, amount) +end + +-- Framework.RemoveAccountBalance(src, _type, amount) +-- Removes the specified amount from the player's account balance of the specified type. +Framework.RemoveAccountBalance = function(src, _type, amount) + local xPlayer = ESX.GetPlayerFromId(src) + return xPlayer.removeAccountMoney(_type, amount) +end + +-- Framework.GetAccountBalance(src, _type) +-- Returns the player's account balance of the specified type. +Framework.GetAccountBalance = function(src, _type) + local xPlayer = ESX.GetPlayerFromId(src) + return xPlayer.getAccount(_type).money +end + +-- Framework.AddItem(src, item, amount, _, _) +-- Adds the specified item to the player's inventory. +Framework.AddItem = function(src, item, amount, slot, metadata) + local xPlayer = ESX.GetPlayerFromId(src) + return xPlayer.addInventoryItem(item, amount) +end + +-- Framework.RemoveItem(src, item, amount, _, _) +-- Removes the specified item from the player's inventory. +Framework.RemoveItem = function(src, item, amount, slot, metadata) + local xPlayer = ESX.GetPlayerFromId(src) + return xPlayer.removeInventoryItem(item, amount) +end + +-- Framework.RegisterUsableItem(item, cb) +-- Registers a usable item with a callback function. +Framework.RegisterUsableItem = function(item, cb) + ESX.RegisterUsableItem(item, cb) +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 \ No newline at end of file diff --git a/modules/framework/qb-core/client.lua b/modules/framework/qb-core/client.lua new file mode 100644 index 0000000..fd33406 --- /dev/null +++ b/modules/framework/qb-core/client.lua @@ -0,0 +1,79 @@ +if GetResourceState('qb-core') ~= 'started' then return end +if GetResourceState('qbx_core') == 'started' then return end + +QBCore = exports['qb-core']:GetCoreObject() + +Framework = {} + +Framework.GetPlayerData = function() + return QBCore.Functions.GetPlayerData() +end + +Framework.GetPlayerMetaData = function(metadata) + return QBCore.Functions.GetPlayerData().metadata[metadata] +end + +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 + +Framework.GetPlayerIdentifier = function() + return QBCore.Functions.GetPlayerData().citizenid +end + +Framework.GetPlayerName = function() + local playerData = QBCore.Functions.GetPlayerData() + return playerData.charinfo.firstname, playerData.charinfo.lastname +end + +Framework.GetPlayerJob = function() + local playerData = QBCore.Functions.GetPlayerData() + return playerData.job.name, playerData.job.label, playerData.job.grade.name, playerData.job.grade.level +end + +Framework.GetPlayerInventory = function() + return QBCore.Functions.GetPlayerData().items +end + +Framework.GetIsPlayerDead = function() + return QBCore.Functions.GetPlayerData().metadata["isdead"] or QBCore.GetPlayerData().metadata["inlaststand"] +end + +Framework.Shared = QBCore.Shared + +RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function() + Wait(1500) + FillBridgeTables() + TriggerEvent('community_bridge:Client:OnPlayerLoaded') +end) + +RegisterNetEvent('QBCore:Client:OnPlayerUnload', function() + ClearClientSideVariables() + TriggerEvent('community_bridge:Client:OnPlayerUnload') +end) + +RegisterNetEvent('QBCore:Client:OnJobUpdate', function(data) + PlayerJobName = data.name + PlayerJobLabel = data.label + PlayerJobGradeName = data.grade.name + PlayerJobGradeLevel = data.grade.level + TriggerEvent('community_bridge:Client:OnPlayerJobUpdate', PlayerJobName, PlayerJobLabel, PlayerJobGradeName, PlayerJobGradeLevel) +end) + +RegisterNetEvent('QBCore:Client:OnGangUpdate', function(data) + PlayerJobName = data.name + PlayerJobLabel = data.label + PlayerJobGradeName = data.grade.name + PlayerJobGradeLevel = data.grade.level + TriggerEvent('community_bridge:Client:OnPlayerGangUpdate', PlayerGangName, PlayerGangLabel, PlayerGangGradeName, PlayerGangGradeLevel) +end) \ No newline at end of file diff --git a/modules/framework/qb-core/server.lua b/modules/framework/qb-core/server.lua new file mode 100644 index 0000000..13e5144 --- /dev/null +++ b/modules/framework/qb-core/server.lua @@ -0,0 +1,258 @@ +if GetResourceState('qb-core') ~= 'started' then return end +if GetResourceState('qbx_core') == 'started' then return end + +QBCore = exports['qb-core']:GetCoreObject() + +Framework = {} + +-- Framework.GetPlayerIdentifier(src) +-- Returns the citizen ID of the player. +Framework.GetPlayerIdentifier = function(src) + return QBCore.Functions.GetPlayer(src).PlayerData.citizenid +end + +-- Framework.GetPlayerName(src) +-- Returns the first and last name of the player. +Framework.GetPlayerName = function(src) + local playerData = QBCore.Functions.GetPlayer(src).PlayerData + return playerData.charinfo.firstname, playerData.charinfo.lastname +end + +-- Framework.GetItem(src, item, metadata) +-- 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} +Framework.GetItem = function(src, item, metadata) + local playerInventory = QBCore.Functions.GetPlayer(src).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 + +-- Framework.GetItemCount(src, item, metadata) +-- Returns the count of items matching the specified name and if passed metadata from the player's inventory. +Framework.GetItemCount = function(src, item, metadata) + local playerInventory = QBCore.Functions.GetPlayer(src).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 + +-- 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} +Framework.GetPlayerInventory = function(src) + local playerItems = QBCore.Functions.GetPlayer(src).PlayerData.items + local repackedTable = {} + for _, v in pairs(playerItems) do + table.insert(repackedTable, { + name = v.name, + count = v.amount, + metadata = v.info, + slot = v.slot, + }) + end + return repackedTable +end + +-- Framework.SetMetadata(src, metadata, value) +-- Adds the specified metadata key and number value to the player's data. +Framework.SetPlayerMetadata = function(src, metadata, value) + local player = QBCore.Functions.GetPlayer(src) + player.Functions.SetMetaData(metadata, value) + return true +end + +-- Framework.GetMetadata(src, metadata) +-- Gets the specified metadata key to the player's data. +Framework.GetPlayerMetadata = function(src, metadata) + local player = QBCore.Functions.GetPlayer(src) + 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. +Framework.AddStress = function(src, value) + local player = QBCore.Functions.GetPlayer(src) + 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. +Framework.RemoveStress = function(src, value) + local player = QBCore.Functions.GetPlayer(src) + 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. +Framework.AddHunger = function(src, value) + local player = QBCore.Functions.GetPlayer(src) + 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 + +-- Framework.AddThirst(src, value) +-- Adds the specified value from the player's thirst level. +Framework.AddThirst = function(src, value) + local player = QBCore.Functions.GetPlayer(src) + 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 + +Framework.GetHunger = function(src) + local player = QBCore.Functions.GetPlayer(src) + local playerData = player.PlayerData + local newHunger = (playerData.metadata.hunger or 0) + return newHunger +end + +Framework.GetThirst = function(src) + local player = QBCore.Functions.GetPlayer(src).PlayerData + local newThirst = (player.metadata.thirst or 0) + return newThirst +end + +-- Framework.GetPlayerPhone(src) +-- Returns the phone number of the player. +Framework.GetPlayerPhone = function(src) + local playerData = QBCore.Functions.GetPlayer(src).PlayerData + return playerData.charinfo.phone +end + +-- Framework.GetPlayerGang(src) +-- Returns the gang name of the player. +Framework.GetPlayerGang = function(src) + local player = QBCore.Functions.GetPlayer(src).PlayerData + return player.gang.name +end + +-- Framework.GetPlayersByJob(jobname) +-- returns a table of player sources that have the specified job name. +Framework.GetPlayersByJob = function(job) + local players = QBCore.Functions.GetPlayers() + local playerList = {} + for _, src in pairs(players) do + local player = QBCore.Functions.GetPlayer(src).PlayerData + if player.job.name == job then + table.insert(playerList, src) + end + end + return playerList +end + +-- Framework.GetPlayerJob(src) +-- Returns the job name, label, grade name, and grade level of the player. +Framework.GetPlayerJob = function(src) + local player = QBCore.Functions.GetPlayer(src).PlayerData + return player.job.name, player.job.label, player.job.grade.name, player.job.grade.level +end + +-- Framework.SetPlayerJob(src, name, grade) +-- Sets the player's job to the specified name and grade. +Framework.SetPlayerJob = function(src, name, grade) + local player = QBCore.Functions.GetPlayer(src) + return player.Functions.SetJob(name, grade) +end + +Framework.ToggleDuty = function(src, status) + local player = QBCore.Functions.GetPlayer(src) + player.Functions.SetJobDuty(status) + TriggerEvent('QBCore:Server:SetDuty', src, player.PlayerData.job.onduty) +end + +-- Framework.AddAccountBalance(src, _type, amount) +-- Adds the specified amount to the player's account balance of the specified type. +Framework.AddAccountBalance = function(src, _type, amount) + local player = QBCore.Functions.GetPlayer(src) + if _type == 'money' then _type = 'cash' end + return player.Functions.AddMoney(_type, amount) +end + +-- Framework.RemoveAccountBalance(src, _type, amount) +-- Removes the specified amount from the player's account balance of the specified type. +Framework.RemoveAccountBalance = function(src, _type, amount) + local player = QBCore.Functions.GetPlayer(src) + if _type == 'money' then _type = 'cash' end + return player.Functions.RemoveMoney(_type, amount) +end + +-- Framework.GetAccountBalance(src, _type) +-- Returns the player's account balance of the specified type. +Framework.GetAccountBalance = function(src, _type) + local playerData = QBCore.Functions.GetPlayer(src).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. +Framework.AddItem = function(src, item, amount, slot, metadata) + local player = QBCore.Functions.GetPlayer(src) + 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. +Framework.RemoveItem = function(src, item, amount, slot, metadata) + local player = QBCore.Functions.GetPlayer(src) + 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 +Framework.SetMetadata = function(src, item, slot, metadata) + local player = QBCore.Functions.GetPlayer(src) + 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 + player.Functions.RemoveItem(item, 1, itemSlot) + return player.Functions.AddItem(item, 1, freeSlot, metadata) +end + +-- Framework.RegisterUsableItem(item, cb) +-- Registers a usable item with a callback function. +Framework.RegisterUsableItem = function(item, cb) + QBCore.Functions.CreateUseableItem(item, cb) +end + +Framework.Commands = {} +Framework.Commands.Add = function(name, help, arguments, argsrequired, callback, permission, ...) + QBCore.Commands.Add(name, help, arguments, argsrequired, callback, permission, ...) +end \ No newline at end of file diff --git a/modules/framework/qbx_core/client.lua b/modules/framework/qbx_core/client.lua new file mode 100644 index 0000000..3d50505 --- /dev/null +++ b/modules/framework/qbx_core/client.lua @@ -0,0 +1,55 @@ +if GetResourceState('qbx_core') ~= 'started' then return end + +QBox = exports.qbx_core + +Framework = {} + +Framework.GetPlayerData = function() + return QBox.GetPlayerData() +end + +Framework.GetPlayerMetaData = function(metadata) + local playerData = QBox.GetPlayerData() + return playerData.metadata[metadata] +end + +Framework.GetPlayerIdentifier = function() + return QBox.GetPlayerData().citizenid +end + +Framework.GetPlayerName = function() + local playerData = QBox.GetPlayerData() + return playerData.charinfo.firstname, playerData.charinfo.lastname +end + +Framework.GetPlayerJob = function() + local playerData = QBox.GetPlayerData() + return playerData.job.name, playerData.job.label, playerData.job.grade.name, playerData.job.grade.level +end + +Framework.GetPlayerInventory = function() + return QBox.GetPlayerData().items +end + +Framework.GetIsPlayerDead = function() + return QBox.GetPlayerData().metadata["isdead"] or QBox.GetPlayerData().metadata["inlaststand"] +end + +RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function() + Wait(1500) + FillBridgeTables() + TriggerEvent('community_bridge:Client:OnPlayerLoaded') +end) + +RegisterNetEvent('QBCore:Client:OnPlayerUnload', function() + ClearClientSideVariables() + TriggerEvent('community_bridge:Client:OnPlayerUnload') +end) + +RegisterNetEvent('QBCore:Client:OnJobUpdate', function(data) + PlayerJobName = data.name + PlayerJobLabel = data.label + PlayerJobGradeName = data.grade.name + PlayerJobGradeLevel = data.grade.level + TriggerEvent('community_bridge:Client:OnPlayerJobUpdate',PlayerJobName, PlayerJobLabel, PlayerJobGradeName, PlayerJobGradeLevel) +end) \ No newline at end of file diff --git a/modules/framework/qbx_core/server.lua b/modules/framework/qbx_core/server.lua new file mode 100644 index 0000000..13592c1 --- /dev/null +++ b/modules/framework/qbx_core/server.lua @@ -0,0 +1,240 @@ +if GetResourceState('qbx_core') ~= 'started' then return end + +local QBox = exports.qbx_core + +Framework = {} + +-- Framework.GetPlayerIdentifier(src) +-- Returns the citizen ID of the player. +Framework.GetPlayerIdentifier = function(src) + local playerData = QBox:GetPlayer(src).PlayerData + if not playerData then return false end + return playerData.citizenid +end + +-- Framework.GetPlayerName(src) +-- Returns the first and last name of the player. +Framework.GetPlayerName = function(src) + local playerData = QBox:GetPlayer(src).PlayerData + return playerData.charinfo.firstname, playerData.charinfo.lastname +end + +-- Framework.GetItem(src, item, metadata) +-- 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} +Framework.GetItem = function(src, item, metadata) + local playerInventory = QBox:GetPlayer(src).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 + +-- Framework.GetItemCount(src, item, metadata) +-- Returns the count of items matching the specified name and if passed metadata from the player's inventory. +Framework.GetItemCount = function(src, item, metadata) + local playerInventory = QBox:GetPlayer(src).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 + +-- 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} +Framework.GetPlayerInventory = function(src) + local playerItems = QBox:GetPlayer(src).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 + +-- Framework.SetMetadata(src, metadata, value) +-- Adds the specified metadata key and number value to the player's data. +Framework.SetPlayerMetadata = function(src, metadata, value) + local player = QBox:GetPlayer(src) + player.Functions.SetMetaData(metadata, value) + return true +end + +-- Framework.GetMetadata(src, metadata) +-- Gets the specified metadata key to the player's data. +Framework.GetPlayerMetadata = function(src, metadata) + local player = QBox:GetPlayer(src) + 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. +Framework.AddStress = function(src, value) + local player = QBox:GetPlayer(src) + 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. +Framework.RemoveStress = function(src, value) + local player = QBox:GetPlayer(src) + 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. +Framework.AddHunger = function(src, value) + local player = QBox:GetPlayer(src) + 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 + +-- Framework.AddThirst(src, value) +-- Adds the specified value from the player's thirst level. +Framework.AddThirst = function(src, value) + local player = QBox:GetPlayer(src) + 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 + +Framework.GetHunger = function(src) + local player = QBox:GetPlayer(src) + local playerData = player.PlayerData + local newHunger = (playerData.metadata.hunger or 0) + return newHunger +end + +Framework.GetThirst = function(src) + local player = QBox:GetPlayer(src) + local playerData = player.PlayerData + local newThirst = (playerData.metadata.thirst or 0) + return newThirst +end + +-- Framework.GetPlayerPhone(src) +-- Returns the phone number of the player. +Framework.GetPlayerPhone = function(src) + local playerData = QBox:GetPlayer(src).PlayerData + return playerData.charinfo.phone +end + +-- Framework.GetPlayerGang(src) +-- Returns the gang name of the player. +Framework.GetPlayerGang = function(src) + local player = QBox:GetPlayer(src).PlayerData + return player.gang.name +end + +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 + +-- Framework.GetPlayerJob(src) +-- Returns the job name, label, grade name, and grade level of the player. +Framework.GetPlayerJob = function(src) + local player = QBox:GetPlayer(src).PlayerData + return player.job.name, player.job.label, player.job.grade.name, player.job.grade.level +end + +-- Framework.SetPlayerJob(src, name, grade) +-- Sets the player's job to the specified name and grade. +Framework.SetPlayerJob = function(src, name, grade) + local player = QBox:GetPlayer(src) + return player.Functions.SetJob(name, grade) +end + +Framework.ToggleDuty = function(src, status) + local playerData = QBox:GetPlayer(src).PlayerData + QBox:SetJobDuty(playerData.citizenid, status) +end + +-- Framework.AddAccountBalance(src, _type, amount) +-- Adds the specified amount to the player's account balance of the specified type. +Framework.AddAccountBalance = function(src, _type, amount) + local player = QBox:GetPlayer(src) + if _type == 'money' then _type = 'cash' end + return player.Functions.AddMoney(_type, amount) +end + +-- Framework.RemoveAccountBalance(src, _type, amount) +-- Removes the specified amount from the player's account balance of the specified type. +Framework.RemoveAccountBalance = function(src, _type, amount) + local player = QBox:GetPlayer(src) + if _type == 'money' then _type = 'cash' end + return player.Functions.RemoveMoney(_type, amount) +end + +-- Framework.GetAccountBalance(src, _type) +-- Returns the player's account balance of the specified type. +Framework.GetAccountBalance = function(src, _type) + local playerData = QBox:GetPlayer(src).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. +Framework.AddItem = function(src, item, amount, slot, metadata) + local player = QBox:GetPlayer(src) + 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. +Framework.RemoveItem = function(src, item, amount, slot, metadata) + local player = QBox:GetPlayer(src) + return player.Functions.RemoveItem(item, amount, slot) +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 +Framework.SetMetadata = function(src, item, slot, metadata) + local player = QBox:GetPlayer(src) + player.Functions.RemoveItem(item, 1, slot) + return player.Functions.AddItem(item, 1, slot, metadata) +end + +-- Framework.RegisterUsableItem(item, cb) +-- Registers a usable item with a callback function. +Framework.RegisterUsableItem = function(item, cb) + return QBox:CreateUseableItem(item, cb) +end \ No newline at end of file diff --git a/modules/fuel/LegacyFuel/client.lua b/modules/fuel/LegacyFuel/client.lua new file mode 100644 index 0000000..e5e6613 --- /dev/null +++ b/modules/fuel/LegacyFuel/client.lua @@ -0,0 +1,12 @@ +if GetResourceState('LegacyFuel') ~= 'started' then return end +Fuel = {} + +Fuel.GetFuel = function(vehicle) + if not DoesEntityExist(vehicle) then return 0.0 end + return exports['LegacyFuel']:GetFuel(vehicle) +end + +Fuel.SetFuel = function(vehicle, fuel, type) + if not DoesEntityExist(vehicle) then return end + return exports['LegacyFuel']:SetFuel(vehicle, fuel) +end \ No newline at end of file diff --git a/modules/fuel/Renewed-Fuel/client.lua b/modules/fuel/Renewed-Fuel/client.lua new file mode 100644 index 0000000..97e17ff --- /dev/null +++ b/modules/fuel/Renewed-Fuel/client.lua @@ -0,0 +1,12 @@ +if GetResourceState('Renewed-Fuel') ~= 'started' then return end +Fuel = {} + +Fuel.GetFuel = function(vehicle) + if not DoesEntityExist(vehicle) then return 0.0 end + return exports['Renewed-Fuel']:GetFuel(vehicle) +end + +Fuel.SetFuel = function(vehicle, fuel, type) + if not DoesEntityExist(vehicle) then return end + return exports['Renewed-Fuel']:SetFuel(vehicle, fuel) +end \ No newline at end of file diff --git a/modules/fuel/_defualts/client.lua b/modules/fuel/_defualts/client.lua new file mode 100644 index 0000000..7b1055b --- /dev/null +++ b/modules/fuel/_defualts/client.lua @@ -0,0 +1,11 @@ +Fuel = Fuel or {} + +Fuel.GetFuel = function(vehicle) + if not DoesEntityExist(vehicle) then return 0.0 end + return GetVehicleFuelLevel(vehicle) +end + +Fuel.SetFuel = function(vehicle, fuel, type) + if not DoesEntityExist(vehicle) then return end + return SetVehicleFuelLevel(vehicle, fuel) +end \ No newline at end of file diff --git a/modules/fuel/cdn-fuel/client.lua b/modules/fuel/cdn-fuel/client.lua new file mode 100644 index 0000000..752d7b4 --- /dev/null +++ b/modules/fuel/cdn-fuel/client.lua @@ -0,0 +1,12 @@ +if GetResourceState('cdn-fuel') ~= 'started' then return end +Fuel = {} + +Fuel.GetFuel = function(vehicle) + if not DoesEntityExist(vehicle) then return 0.0 end + return exports['cdn-fuel']:GetFuel(vehicle) +end + +Fuel.SetFuel = function(vehicle, fuel, type) + if not DoesEntityExist(vehicle) then return end + return exports['cdn-fuel']:SetFuel(vehicle, fuel) +end \ No newline at end of file diff --git a/modules/fuel/okokGasStation/client.lua b/modules/fuel/okokGasStation/client.lua new file mode 100644 index 0000000..f263a31 --- /dev/null +++ b/modules/fuel/okokGasStation/client.lua @@ -0,0 +1,12 @@ +if GetResourceState('okokGasStation') ~= 'started' then return end +Fuel = {} + +Fuel.GetFuel = function(vehicle) + if not DoesEntityExist(vehicle) then return 0.0 end + return exports['okokGasStation']:GetFuel(vehicle) +end + +Fuel.SetFuel = function(vehicle, fuel, type) + if not DoesEntityExist(vehicle) then return end + return exports['okokGasStation']:SetFuel(vehicle, fuel) +end \ No newline at end of file diff --git a/modules/fuel/ox_fuel/client.lua b/modules/fuel/ox_fuel/client.lua new file mode 100644 index 0000000..2b03c6c --- /dev/null +++ b/modules/fuel/ox_fuel/client.lua @@ -0,0 +1,14 @@ +if GetResourceState('cdn-fuel') ~= 'started' then return end +Fuel = {} + +Fuel.GetFuel = function(vehicle) + if not DoesEntityExist(vehicle) then return 0.0 end + return Entity(vehicle).state.fuel +end + +Fuel.SetFuel = function(vehicle, fuel, type) + if not DoesEntityExist(vehicle) then return end + local currentFuel = Entity(vehicle).state.fuel + Entity(vehicle).state.fuel = currentFuel + fuel + return Entity(vehicle).state.fuel +end \ No newline at end of file diff --git a/modules/fuel/ps-fuel/client.lua b/modules/fuel/ps-fuel/client.lua new file mode 100644 index 0000000..1d51570 --- /dev/null +++ b/modules/fuel/ps-fuel/client.lua @@ -0,0 +1,12 @@ +if GetResourceState('ps-fuel') ~= 'started' then return end +Fuel = {} + +Fuel.GetFuel = function(vehicle) + if not DoesEntityExist(vehicle) then return 0.0 end + return exports['ps-fuel']:GetFuel(vehicle) +end + +Fuel.SetFuel = function(vehicle, fuel, type) + if not DoesEntityExist(vehicle) then return end + return exports['ps-fuel']:SetFuel(vehicle, fuel) +end \ No newline at end of file diff --git a/modules/fuel/ti_fuel/client.lua b/modules/fuel/ti_fuel/client.lua new file mode 100644 index 0000000..234734c --- /dev/null +++ b/modules/fuel/ti_fuel/client.lua @@ -0,0 +1,13 @@ +if GetResourceState('ti_fuel') ~= 'started' then return end +Fuel = {} + +Fuel.GetFuel = function(vehicle) + if not DoesEntityExist(vehicle) then return 0.0, type end + local level, type = exports["ti_fuel"]:getFuel(vehicle) + return level, type +end + +Fuel.SetFuel = function(vehicle, fuel, type) + if not DoesEntityExist(vehicle) then return end + return exports['ti_fuel']:setFuel(vehicle, fuel, type or "RON91") +end \ No newline at end of file diff --git a/modules/fuel/x-fuel/client.lua b/modules/fuel/x-fuel/client.lua new file mode 100644 index 0000000..0b34d99 --- /dev/null +++ b/modules/fuel/x-fuel/client.lua @@ -0,0 +1,13 @@ +if GetResourceState('x-fuel') ~= 'started' then return end +Fuel = {} + +Fuel.GetFuel = function(vehicle) + if not DoesEntityExist(vehicle) then return 0.0, type end + local level, type = exports["x-fuel"]:getFuel(vehicle) + return level, type +end + +Fuel.SetFuel = function(vehicle, fuel, type) + if not DoesEntityExist(vehicle) then return end + return exports['x-fuel']:SetFuel(vehicle, fuel) +end \ No newline at end of file diff --git a/modules/input/client.lua b/modules/input/client.lua new file mode 100644 index 0000000..8993def --- /dev/null +++ b/modules/input/client.lua @@ -0,0 +1,291 @@ + +if GetResourceState('ox_lib') ~= 'started' and GetResourceState('qb-menu') ~= 'started' then return end +-- { +-- header = "Test", +-- submitText = "Bill", +-- inputs = { +-- { +-- text = "Citizen ID (#)", -- text you want to be displayed as a place holder +-- name = "citizenid", -- name of the input should be unique otherwise it might override +-- type = "text", -- type of the input +-- isRequired = true, -- Optional [accepted values: true | false] but will submit the form if no value is inputted +-- -- default = "CID-1234", -- Default text option, this is optional +-- }, +-- { +-- text = "Secret Code (Give to Nobody)", -- text you want to be displayed as a place holder +-- name = "code", -- name of the input should be unique otherwise it might override +-- type = "password", -- type of the input +-- isRequired = true, -- Optional [accepted values: true | false] but will submit the form if no value is inputted +-- -- default = "password123", -- Default text option, this is optional +-- }, +-- { +-- text = "Bill Price ($)", -- text you want to be displayed as a place holder +-- name = "billprice", -- name of the input should be unique otherwise it might override +-- type = "number", -- type of the input - number will not allow non-number characters in the field so only accepts 0-9 +-- isRequired = false, -- Optional [accepted values: true | false] but will submit the form if no value is inputted +-- -- default = 1, -- Default number option, this is optional +-- }, +-- { +-- text = "Bill Type", -- text you want to be displayed as a input header +-- name = "billtype", -- name of the input should be unique otherwise it might override +-- type = "radio", -- type of the input - Radio is useful for "or" options e.g; billtype = Cash OR Bill OR bank +-- options = { -- The options (in this case for a radio) you want displayed, more than 6 is not recommended +-- { value = "bill", text = "Bill" }, -- Options MUST include a value and a text option +-- { value = "cash", text = "Cash" }, -- Options MUST include a value and a text option +-- { value = "bank", text = "Bank" } -- Options MUST include a value and a text option +-- }, +-- -- default = "cash", -- Default radio option, must match a value from above, this is optional +-- }, +-- { +-- text = "Include Tax?", -- text you want to be displayed as a input header +-- name = "taxincl", -- name of the input should be unique otherwise it might override +-- type = "checkbox", -- type of the input - Check is useful for "AND" options e.g; taxincle = gst AND business AND othertax +-- options = { -- The options (in this case for a check) you want displayed, more than 6 is not recommended +-- { value = "gst", text = "10% incl."}, -- Options MUST include a value and a text option +-- { value = "business", text = "35% incl.", checked = true }, -- Options MUST include a value and a text option, checked = true is default value, optional +-- { value = "othertax", text = "15% incl."} -- Options MUST include a value and a text option +-- } +-- }, +-- { +-- text = "Some Select", -- text you want to be displayed as a input header +-- name = "someselect", -- name of the input should be unique otherwise it might override +-- type = "select", -- type of the input - Select is useful for 3+ amount of "or" options e.g; someselect = none OR other OR other2 OR other3...etc +-- options = { -- Select drop down options, the first option will by default be selected +-- { value = "none", text = "None" }, -- Options MUST include a value and a text option +-- { value = "other", text = "Other"}, -- Options MUST include a value and a text option +-- { value = "other2", text = "Other2" }, -- Options MUST include a value and a text option +-- { value = "other3", text = "Other3" }, -- Options MUST include a value and a text option +-- { value = "other4", text = "Other4" }, -- Options MUST include a value and a text option +-- { value = "other5", text = "Other5" }, -- Options MUST include a value and a text option +-- { value = "other6", text = "Other6" }, -- Options MUST include a value and a text option +-- }, +-- -- default = 'other3', -- Default select option, must match a value from above, this is optional +-- } +-- }, +-- }) + +-- local input = lib.inputDialog('Dialog title', { +-- {type = 'input', label = 'Text input', description = 'Some input description', required = true, min = 4, max = 16}, +-- {type = 'number', label = 'Number input', description = 'Some number description', icon = 'hashtag'}, +-- {type = 'checkbox', label = 'Simple checkbox'}, +-- {type = 'color', label = 'Colour input', default = '#eb4034'}, +-- {type = 'date', label = 'Date input', icon = {'far', 'calendar'}, default = true, format = "DD/MM/YYYY"} +-- }) + + +--QB types: text, password, number, radio, checkbox, select, +-- +-- "input", "number", "checkbox", "select", "multi-select", "slider", "color", "date", "date-range", "time", "textarea", +Input = {} + + +-- ox to Qb +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, + placeholder = v.default, + } + if v.type == "select" then + input.text = "" + input.options = { + {value = v.value, text = v.label} + } + elseif v.type == "checkbox" then + input.text = "" + input.options = { + {value = v.value, text = v.label} + } + end + table.insert(returnData, input) + end + return returnData +end + +-- qb to ox + +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 + +--Open menu + +function Input.Open(title, data, isQBFormat, submitText) + if isQBFormat then + local inputs = data.inputs + if BridgeClientConfig.InputSystem == "ox" then + return lib.inputDialog(title, QBToOxInput(inputs)) + elseif BridgeClientConfig.InputSystem == "qb" then + return exports['qb-input']:ShowInput({ + header = title, + submitText = submitText or "Submit", + inputs = inputs + }) + end + else + if BridgeClientConfig.InputSystem == "ox" then + return lib.inputDialog(title, data) + elseif BridgeClientConfig.InputSystem == "qb" then + return exports['qb-input']:ShowInput({ + header = title, + submitText = submitText or "Submit", + inputs = OxToQBInput(data) + }) + end + end + return id +end + +--[[ +-- Unit tests +local thisIsQB = { + header = "Test", + submitText = "Bill", + inputs = { + { + text = "Citizen ID (#)", -- text you want to be displayed as a place holder + name = "citizenid", -- name of the input should be unique otherwise it might override + type = "text", -- type of the input + isRequired = true, -- Optional [accepted values: true | false] but will submit the form if no value is inputted + -- default = "CID-1234", -- Default text option, this is optional + }, + { + text = "Secret Code (Give to Nobody)", -- text you want to be displayed as a place holder + name = "code", -- name of the input should be unique otherwise it might override + type = "password", -- type of the input + isRequired = true, -- Optional [accepted values: true | false] but will submit the form if no value is inputted + -- default = "password123", -- Default text option, this is optional + }, + { + text = "Bill Price ($)", -- text you want to be displayed as a place holder + name = "billprice", -- name of the input should be unique otherwise it might override + type = "number", -- type of the input - number will not allow non-number characters in the field so only accepts 0-9 + isRequired = false, -- Optional [accepted values: true | false] but will submit the form if no value is inputted + -- default = 1, -- Default number option, this is optional + }, + { + text = "Bill Type", -- text you want to be displayed as a input header + name = "billtype", -- name of the input should be unique otherwise it might override + type = "radio", -- type of the input - Radio is useful for "or" options e.g; billtype = Cash OR Bill OR bank + options = { -- The options (in this case for a radio) you want displayed, more than 6 is not recommended + { value = "bill", text = "Bill" }, -- Options MUST include a value and a text option + { value = "cash", text = "Cash" }, -- Options MUST include a value and a text option + { value = "bank", text = "Bank" } -- Options MUST include a value and a text option + }, + -- default = "cash", -- Default radio option, must match a value from above, this is optional + }, + { + text = "Include Tax?", -- text you want to be displayed as a input header + name = "taxincl", -- name of the input should be unique otherwise it might override + type = "checkbox", -- type of the input - Check is useful for "AND" options e.g; taxincle = gst AND business AND othertax + options = { -- The options (in this case for a check) you want displayed, more than 6 is not recommended + { value = "gst", text = "10% incl."}, -- Options MUST include a value and a text option + { value = "business", text = "35% incl.", checked = true }, -- Options MUST include a value and a text option, checked = true is default value, optional + { value = "othertax", text = "15% incl."} -- Options MUST include a value and a text option + } + }, + { + text = "Some Select", -- text you want to be displayed as a input header + name = "someselect", -- name of the input should be unique otherwise it might override + type = "select", -- type of the input - Select is useful for 3+ amount of "or" options e.g; someselect = none OR other OR other2 OR other3...etc + options = { -- Select drop down options, the first option will by default be selected + { value = "none", text = "None" }, -- Options MUST include a value and a text option + { value = "other", text = "Other"}, -- Options MUST include a value and a text option + { value = "other2", text = "Other2" }, -- Options MUST include a value and a text option + { value = "other3", text = "Other3" }, -- Options MUST include a value and a text option + { value = "other4", text = "Other4" }, -- Options MUST include a value and a text option + { value = "other5", text = "Other5" }, -- Options MUST include a value and a text option + { value = "other6", text = "Other6" }, -- Options MUST include a value and a text option + }, + -- default = 'other3', -- Default select option, must match a value from above, this is optional + } + }, +} + +local thisIsOx = { + {type = 'input', label = 'Text input', description = 'Some input description', required = true, min = 4, max = 16}, + {type = 'number', label = 'Number input', description = 'Some number description', icon = 'hashtag'}, + {type = 'checkbox', label = 'Simple checkbox'}, + {type = 'color', label = 'Colour input', default = '#eb4034'}, + {type = 'date', label = 'Date input', icon = {'far', 'calendar'}, default = true, format = "DD/MM/YYYY"} +} + +-- qb to ox +RegisterCommand('inputtest1', function() + Input.Open("Test", thisIsQB, true) +end) + +-- ox to qb +RegisterCommand('inputtest2', function() + Input.Open("Test", thisIsOx, false) +end) +--]] \ No newline at end of file diff --git a/modules/inventory/_default/client.lua b/modules/inventory/_default/client.lua new file mode 100644 index 0000000..db02090 --- /dev/null +++ b/modules/inventory/_default/client.lua @@ -0,0 +1,10 @@ +Inventory = Inventory or {} + +Inventory.GetItemInfo = function(item) + print('client funct') + return Framework.GetItemInfo(item) +end + +Inventory.GetImagePath = function(item) + return "https://avatars.githubusercontent.com/u/47620135" +end \ No newline at end of file diff --git a/modules/inventory/_default/server.lua b/modules/inventory/_default/server.lua new file mode 100644 index 0000000..b33ed1f --- /dev/null +++ b/modules/inventory/_default/server.lua @@ -0,0 +1,33 @@ +Inventory = Inventory or {} + +Inventory.AddItem = function(src, item, count, slot, metadata) + return Framework.AddItem(src, item, count, slot, metadata) +end + +Inventory.RemoveItem = function(src, item, count, slot, metadata) + return Framework.RemoveItem(src, item.name, count, slot, metadata) +end + +Inventory.GetItemInfo = function(item) + return false, print("This Inventory Has Not Been Bridged For An Item Info Feature.") +end + +Inventory.GetItemCount = function(src, item, metadata) + return Framework.GetItemCount(src, item, metadata) +end + +Inventory.GetInventoryItems = function(src) + return Framework.GetPlayerInventory(src) +end + +Inventory.SetMetadata = function(src, item, slot, metadata) + return Framework.SetMetadata(src, item, slot, metadata) +end + +Inventory.OpenStash = function(src, id, label, slots, weight, owner, groups, coords) + return false, print("This Inventory Has Not Been Bridged For A Stash Feature.") +end + +Inventory.GetImagePath = function(item) + return "https://avatars.githubusercontent.com/u/47620135" +end \ No newline at end of file diff --git a/modules/inventory/codem-inventory/client.lua b/modules/inventory/codem-inventory/client.lua new file mode 100644 index 0000000..93d902d --- /dev/null +++ b/modules/inventory/codem-inventory/client.lua @@ -0,0 +1,21 @@ +if GetResourceState('codem-inventory') ~= 'started' then return end +Inventory = Inventory or {} + +Inventory.GetItemInfo = function(item) + local itemData = exports['codem-inventory']:GetItemList() + if not itemData[item] then return {} end + local repackedTable = { + name = itemData.name or "Missing Name", + label = itemData.label or "Missing Label", + stack = itemData.unique or "false", + weight = itemData.weight or "0", + description = itemData.description or "none", + image = itemData.image or Inventory.GetImagePath(item), + } + return repackedTable +end + +Inventory.GetImagePath = function(item) + local imagePath = string.format("nui://codem-inventory/html/images/%s.png", item) + return imagePath or "https://avatars.githubusercontent.com/u/47620135" +end diff --git a/modules/inventory/codem-inventory/server.lua b/modules/inventory/codem-inventory/server.lua new file mode 100644 index 0000000..aff87d7 --- /dev/null +++ b/modules/inventory/codem-inventory/server.lua @@ -0,0 +1,78 @@ +if GetResourceState('codem-inventory') ~= 'started' then return end + +Inventory = Inventory or {} + +Inventory.AddItem = function(src, item, count, slot, metadata) + return exports['codem-inventory']:AddItem(src, item, count, slot, metadata) +end + +Inventory.RemoveItem = function(src, item, count, slot, metadata) + if metadata == nil then + return exports['codem-inventory']:RemoveItem(src, item, count, slot) + else + local items = exports['codem-inventory']:GetInventory(nil, src) + for _, itemInfo in pairs(items) do + if itemInfo.name == item then + if itemInfo.info == metadata then + return exports['codem-inventory']:RemoveItem(src, item, count, itemInfo.slot) + end + end + end + end +end + +Inventory.GetItemInfo = function(item) + local itemData = exports['codem-inventory']:GetItemList() + if not itemData[item] then return {} end + local repackedTable = { + name = itemData.name or "Missing Name", + label = itemData.label or "Missing Label", + stack = itemData.unique or "false", + weight = itemData.weight or "0", + description = itemData.description or "none", + image = itemData.image or Inventory.GetImagePath(item), + } + return repackedTable +end + +Inventory.GetItemCount = function(src, item, metadata) + if metadata == nil then + return exports['codem-inventory']:GetItemsTotalAmount(src, item) + else + local count = 0 + local items = exports['codem-inventory']:GetInventory(nil, src) + for _, itemInfo in pairs(items) do + if itemInfo.name == item and itemInfo.info == metadata then + count = count + itemInfo.amount + end + return count + end + end +end + +Inventory.GetInventoryItems = function(src) + local items = exports['codem-inventory']:GetInventory(nil, src) + local repackedTable = {} + for _, v in pairs(items) do + table.insert(repackedTable, { + name = v.name, + count = v.amount, + metadata = v.info, + slot = v.slot, + }) + end + return items +end + +Inventory.SetMetadata = function(src, item, slot, metadata) + exports['codem-inventory']:SetItemMetadata(src, slot, metadata) +end + +Inventory.OpenStash = function(src, id, label, slots, weight, owner, groups, coords) + TriggerEvent('codem-inventory:server:openstash', id, slots, weight, label) +end + +Inventory.GetImagePath = function(item) + local imagePath = string.format("nui://codem-inventory/html/images/%s.png", item) + return imagePath or "https://avatars.githubusercontent.com/u/47620135" +end \ No newline at end of file diff --git a/modules/inventory/core_inventory/client.lua b/modules/inventory/core_inventory/client.lua new file mode 100644 index 0000000..124acd1 --- /dev/null +++ b/modules/inventory/core_inventory/client.lua @@ -0,0 +1,7 @@ +if GetResourceState('core_inventory') ~= 'started' then return end + +Inventory = Inventory or {} + +Inventory.TestFunction = function(item) + return 'test funct client inv' +end \ No newline at end of file diff --git a/modules/inventory/core_inventory/server.lua b/modules/inventory/core_inventory/server.lua new file mode 100644 index 0000000..bf8e186 --- /dev/null +++ b/modules/inventory/core_inventory/server.lua @@ -0,0 +1,7 @@ +if GetResourceState('core_inventory') ~= 'started' then return end + +Inventory = Inventory or {} + +Inventory.TestFunction = function(item) + return 'test funct server inv' +end \ No newline at end of file diff --git a/modules/inventory/origen_inventory/client.lua b/modules/inventory/origen_inventory/client.lua new file mode 100644 index 0000000..b8bfa99 --- /dev/null +++ b/modules/inventory/origen_inventory/client.lua @@ -0,0 +1,24 @@ +if GetResourceState('origen_inventory') ~= 'started' then return end + +Inventory = Inventory or {} + +local origen_inventory = exports.origen_inventory + +Inventory.GetItemInfo = function(item) + local itemData = origen_inventory:Items(item) + local repackedTable = { + name = itemData.name or "Missing Name", + label = itemData.label or "Missing Label", + stack = itemData.unique or "false", + weight = itemData.weight or "0", + description = itemData.description or "none", + image = itemData.image or Inventory.GetImagePath(item), + } + return repackedTable or {} +end + +Inventory.GetImagePath = function(item) + local file = LoadResourceFile("origen_inventory", string.format("html/images/%s.png", item)) + local imagePath = file and string.format("nui://origen_inventory/html/images/%s.png", item) + return imagePath or "https://avatars.githubusercontent.com/u/47620135" +end \ No newline at end of file diff --git a/modules/inventory/origen_inventory/server.lua b/modules/inventory/origen_inventory/server.lua new file mode 100644 index 0000000..0bf768e --- /dev/null +++ b/modules/inventory/origen_inventory/server.lua @@ -0,0 +1,80 @@ +if GetResourceState('origen_inventory') ~= 'started' then return end + +Inventory = Inventory or {} + +local origen_inventory = exports.origen_inventory + +Inventory.AddItem = function(src, item, count, slot, metadata) + if not origen_inventory:CanCarryItem(src, item, count) then + return Bridge.notify.SendNotify(src, "Inventory Full", "error", 5000) + end + return origen_inventory:AddItem(src, item, count, nil, nil, metadata) +end + +Inventory.RemoveItem = function(src, item, count, slot, metadata) + return origen_inventory:RemoveItem(src, item, count, metadata) +end + +Inventory.GetItemInfo = function(item) + local itemData = origen_inventory:Items(item) + local repackedTable = { + name = itemData.name or "Missing Name", + label = itemData.label or "Missing Label", + stack = itemData.unique or "false", + weight = itemData.weight or "0", + description = itemData.description or "none", + image = itemData.image or Inventory.GetImagePath(item), + } + return repackedTable or {} +end + +Inventory.GetItemCount = function(src, item, metadata) + if not metadata then + return origen_inventory:GetItemTotalAmount(src, item) + else + local items = origen_inventory:GetInventory(src) + local count = 0 + for _, itemInfo in pairs(items) do + if itemInfo.name == item and itemInfo.info == metadata then + count = count + itemInfo.amount + end + end + return count + end +end + +Inventory.GetPlayerInventory = function(src) + local playerItems = origen_inventory:GetInventory(src) + local repackedTable = {} + for _, v in pairs(playerItems) do + table.insert(repackedTable, { + name = v.name, + count = v.amount, + metadata = v.info, + slot = v.slot, + }) + end + return repackedTable +end + +Inventory.CanCarryItem = function(src, item, count) + return origen_inventory:CanCarryItems(src, item, count) +end + +Inventory.RegisterStash = function(id, label, slots, weight, owner, groups, coords) + return origen_inventory:RegisterStash(id, { label = label, slots = slots, weight = weight }) +end + +Inventory.OpenStash = function(src, id, label, slots, weight, owner, groups, coords) + return origen_inventory:OpenInventory(src, 'stash', id) +end + +Inventory.SetMetadata = function(src, item, slot, metadata) + origen_inventory:SetItemMetadata(src, item, slot, metadata) +end + +Inventory.GetImagePath = function(item) + local file = LoadResourceFile("origen_inventory", string.format("html/images/%s.png", item)) + local imagePath = file and string.format("nui://origen_inventory/html/images/%s.png", item) + return imagePath or "https://avatars.githubusercontent.com/u/47620135" +end \ No newline at end of file diff --git a/modules/inventory/ox_inventory/client.lua b/modules/inventory/ox_inventory/client.lua new file mode 100644 index 0000000..83a2f18 --- /dev/null +++ b/modules/inventory/ox_inventory/client.lua @@ -0,0 +1,26 @@ +if GetResourceState('ox_inventory') ~= 'started' then return end +local ox_inventory = exports.ox_inventory + +Inventory = Inventory or {} + +Inventory.GetItemInfo = function(item) + local itemData = ox_inventory:Items(item) + if not itemData then return {} end + local repackedTable = { + name = itemData.name or "Missing Name", + label = itemData.label or "Missing Label", + stack = itemData.stack or "true", + weight = itemData.weight or "0", + description = itemData.description or "none", + image = (itemData.client and itemData.client.image) or Inventory.GetImagePath(item), + } + return repackedTable +end + +Inventory.GetImagePath = function(item) + local file = LoadResourceFile("ox_inventory", string.format("web/images/%s.png", item)) + local imagePath = file and string.format("nui://ox_inventory/web/images/%s.png", item) + return imagePath or "https://avatars.githubusercontent.com/u/47620135" +end + +--Bridge.RegisterModule("Inventory", Inventory) \ No newline at end of file diff --git a/modules/inventory/ox_inventory/server.lua b/modules/inventory/ox_inventory/server.lua new file mode 100644 index 0000000..01ac955 --- /dev/null +++ b/modules/inventory/ox_inventory/server.lua @@ -0,0 +1,67 @@ +if GetResourceState('ox_inventory') ~= 'started' then return end + +local ox_inventory = exports.ox_inventory + +Inventory = Inventory or {} + +Inventory.AddItem = function(src, item, count, slot, metadata) + return ox_inventory:AddItem(src, item, count, metadata) +end + +Inventory.RemoveItem = function(src, item, count, slot, metadata) + return ox_inventory:RemoveItem(src, item, count, metadata, slot) +end + +Inventory.GetItem = function(src, item, metadata) + return ox_inventory:GetItem(src, item, metadata, false) +end + +Inventory.GetItemCount = function(src, item, metadata) + return ox_inventory:GetItemCount(src, item, metadata, false) +end + +Inventory.GetPlayerInventory = function(src) + return ox_inventory:GetInventoryItems(src, false) +end + +Inventory.CanCarryItem = function(src, item, count) + return ox_inventory:CanCarryItem(src, item, count) +end + +Inventory.RegisterStash = function(id, label, slots, weight, owner, groups, coords) + return ox_inventory:RegisterStash(id, label, slots, weight, owner) +end + +Inventory.OpenStash = function(src, id, label, slots, weight, owner, groups, coords) + TriggerClientEvent('ox_inventory:openInventory', src, 'stash', 'stash_' .. id) +end + +Inventory.GetItemInfo = function(item) + local itemData = ox_inventory:Items(item) + if not itemData then return {} end + local repackedTable = { + name = itemData.name or "Missing Name", + label = itemData.label or "Missing Label", + stack = itemData.stack or "true", + weight = itemData.weight or "0", + description = itemData.description or "none", + image = itemData.client.image or Inventory.GetImagePath(item), + } + return repackedTable +end + +Inventory.SetMetadata = function(src, item, slot, metadata) + ox_inventory:SetMetadata(src, slot, metadata) +end + +Inventory.UpdatePlate = function(oldplate, newplate) + ox_inventory:UpdateVehicle(oldplate, newplate) + if GetResourceState('jg-mechanic') ~= 'started' then return end + exports["jg-mechanic"]:vehiclePlateUpdated(oldplate, newplate) +end + +Inventory.GetImagePath = function(item) + local file = LoadResourceFile("ox_inventory", string.format("web/images/%s.png", item)) + local imagePath = file and string.format("nui://ox_inventory/web/images/%s.png", item) + return imagePath or "https://avatars.githubusercontent.com/u/47620135" +end \ No newline at end of file diff --git a/modules/inventory/ps-inventory/client.lua b/modules/inventory/ps-inventory/client.lua new file mode 100644 index 0000000..f031826 --- /dev/null +++ b/modules/inventory/ps-inventory/client.lua @@ -0,0 +1,15 @@ +if GetResourceState('ps-inventory') ~= 'started' then return end + +Inventory = Inventory or {} + +RegisterNetEvent('community_bridge:client:ps-inventory:openStash', function(id, data) + if source ~= 65535 then return end + TriggerEvent('ps-inventory:client:SetCurrentStash', id) + TriggerServerEvent('ps-inventory:server:OpenInventory', 'stash', id, { maxweight = data.weight, slots = data.slots }) +end) + +Inventory.GetImagePath = function(item) + local file = LoadResourceFile("ps-inventory", string.format("html/images/%s.png", item)) + local imagePath = file and string.format("nui://ps-inventory/html/images/%s.png", item) + return imagePath or "https://avatars.githubusercontent.com/u/47620135" +end \ No newline at end of file diff --git a/modules/inventory/ps-inventory/server.lua b/modules/inventory/ps-inventory/server.lua new file mode 100644 index 0000000..bf0df31 --- /dev/null +++ b/modules/inventory/ps-inventory/server.lua @@ -0,0 +1,17 @@ +if GetResourceState('ps-inventory') ~= 'started' then return end + +Inventory = Inventory or {} + +Inventory.RegisterStash = function(id, label, slots, weight, owner, groups, coords) + return true +end + +Inventory.OpenStash = function(src, id, label, slots, weight, owner, groups, coords) + TriggerClientEvent('community_bridge:client:ps-inventory:openStash', src, id, { label = label, maxweight = weight, slots = slots, }) +end + +Inventory.GetImagePath = function(item) + local file = LoadResourceFile("ps-inventory", string.format("html/images/%s.png", item)) + local imagePath = file and string.format("nui://ps-inventory/html/images/%s.png", item) + return imagePath or "https://avatars.githubusercontent.com/u/47620135" +end \ No newline at end of file diff --git a/modules/inventory/qb-inventory/client.lua b/modules/inventory/qb-inventory/client.lua new file mode 100644 index 0000000..fc28b4a --- /dev/null +++ b/modules/inventory/qb-inventory/client.lua @@ -0,0 +1,15 @@ +if GetResourceState('qb-inventory') ~= 'started' then return end + +Inventory = Inventory or {} + +RegisterNetEvent('community_bridge:client:qb-inventory:openStash', function(id, data) + if source ~= 65535 then return end + TriggerEvent("inventory:client:SetCurrentStash", id) + TriggerServerEvent('inventory:server:OpenInventory', 'stash', id, { maxweight = data.weight, slots = data.slots }) +end) + +Inventory.GetImagePath = function(item) + local file = LoadResourceFile("qb-inventory", string.format("html/images/%s.png", item)) + local imagePath = file and string.format("nui://qb-inventory/html/images/%s.png", item) + return imagePath or "https://avatars.githubusercontent.com/u/47620135" +end \ No newline at end of file diff --git a/modules/inventory/qb-inventory/server.lua b/modules/inventory/qb-inventory/server.lua new file mode 100644 index 0000000..f2604e8 --- /dev/null +++ b/modules/inventory/qb-inventory/server.lua @@ -0,0 +1,17 @@ +if GetResourceState('qb-inventory') ~= 'started' then return end + +Inventory = Inventory or {} + +Inventory.RegisterStash = function(id, label, slots, weight, owner, groups, coords) + return true +end + +Inventory.OpenStash = function(src, id, label, slots, weight, owner, groups, coords) + TriggerClientEvent('community_bridge:client:qb-inventory:openStash', src, id, { weight = weight, slots = slots }) +end + +Inventory.GetImagePath = function(item) + local file = LoadResourceFile("qb-inventory", string.format("html/images/%s.png", item)) + local imagePath = file and string.format("nui://qb-inventory/html/images/%s.png", item) + return imagePath or "https://avatars.githubusercontent.com/u/47620135" +end \ No newline at end of file diff --git a/modules/inventory/qs-inventory/client.lua b/modules/inventory/qs-inventory/client.lua new file mode 100644 index 0000000..e54e334 --- /dev/null +++ b/modules/inventory/qs-inventory/client.lua @@ -0,0 +1,27 @@ +if GetResourceState('qs-inventory') ~= 'started' then return end + +Inventory = Inventory or {} + +Inventory.OpenStash = function(id) + exports['qs-inventory']:RegisterStash(id, 50, 50000) +end + +Inventory.GetItemInfo = function(item) + local itemData = exports['qs-inventory']:GetItemList() + if not itemData[item] then return {} end + local repackedTable = { + name = itemData.name or "Missing Name", + label = itemData.label or "Missing Label", + stack = itemData.unique or "false", + weight = itemData.weight or "0", + description = itemData.description or "none", + image = itemData.image or Inventory.GetImagePath(item), + } + return repackedTable +end + +Inventory.GetImagePath = function(item) + local file = LoadResourceFile("qs-inventory", string.format("html/images/%s.png", item)) + local imagePath = file and string.format("nui://qs-inventory/html/images/%s.png", item) + return imagePath or "https://avatars.githubusercontent.com/u/47620135" +end \ No newline at end of file diff --git a/modules/inventory/qs-inventory/server.lua b/modules/inventory/qs-inventory/server.lua new file mode 100644 index 0000000..7fab8cc --- /dev/null +++ b/modules/inventory/qs-inventory/server.lua @@ -0,0 +1,67 @@ +if GetResourceState('qs-inventory') ~= 'started' then return end + +Inventory = Inventory or {} + +Inventory.AddItem = function(src, item, count, slot, metadata) + if not exports['qs-inventory']:CanCarryItem(src, item, count) then return false end + return exports['qs-inventory']:AddItem(src, item, count, slot, metadata) +end + +Inventory.RemoveItem = function(src, item, count, slot, metadata) + return exports['qs-inventory']:RemoveItem(src, item, count, slot, metadata) +end + +Inventory.GetItemCount = function(src, item, metadata) + return exports['qs-inventory']:GetItemTotalAmount(src, item) +end + +Inventory.GetPlayerInventory = function(src) + local playerItems = exports['qs-inventory']:GetInventory(src) + local repackedTable = {} + for _, v in pairs(playerItems) do + table.insert(repackedTable, { + name = v.name, + count = v.amount, + metadata = v.info, + slot = v.slot, + }) + end + return repackedTable +end + +Inventory.CanCarryItem = function(src, item, count) + return exports['qs-inventory']:CanCarryItem(src, item, count) +end + +Inventory.RegisterStash = function(id, label, slots, weight, owner, groups, coords) + return true +end + +Inventory.OpenStash = function(src, id, label, slots, weight, owner, groups, coords) + TriggerEvent("inventory:server:OpenInventory", "stash", id, { maxweight = weight, slots = slots }) + TriggerClientEvent("inventory:client:SetCurrentStash",src, id) +end + +Inventory.GetItemInfo = function(item) + local itemData = exports['qs-inventory']:GetItemList() + if not itemData[item] then return {} end + local repackedTable = { + name = itemData.name or "Missing Name", + label = itemData.label or "Missing Label", + stack = itemData.unique or "false", + weight = itemData.weight or "0", + description = itemData.description or "none", + image = itemData.image or Inventory.GetImagePath(item), + } + return repackedTable +end + +Inventory.SetMetadata = function(src, item, slot, metadata) + return exports['qs-inventory']:SetItemMetadata(src, slot, metadata) +end + +Inventory.GetImagePath = function(item) + local file = LoadResourceFile("qs-inventory", string.format("html/images/%s.png", item)) + local imagePath = file and string.format("nui://qs-inventory/html/images/%s.png", item) + return imagePath or "https://avatars.githubusercontent.com/u/47620135" +end \ No newline at end of file diff --git a/modules/inventory/tgiann-inventory/client.lua b/modules/inventory/tgiann-inventory/client.lua new file mode 100644 index 0000000..41cfc13 --- /dev/null +++ b/modules/inventory/tgiann-inventory/client.lua @@ -0,0 +1,29 @@ +if GetResourceState('tgiann-inventory') ~= 'started' then return end +local tgiann = exports["tgiann-inventory"] + +Inventory = Inventory or {} + +Inventory.OpenStash = function(id) + -- open stash export... not sure what it is yet. +end + +Inventory.GetItemInfo = function(item) + local itemData = tgiann:GetItemList() + if not itemData[item] then return {} end + local repackedTable = { + name = itemData.name or "Missing Name", + label = itemData.label or "Missing Label", + stack = itemData.unique or "false", + weight = itemData.weight or "0", + description = itemData.description or "none", + image = itemData.image or Inventory.GetImagePath(item), + } + return repackedTable +end + +Inventory.GetImagePath = function(item) + local pngPath = LoadResourceFile("inventory_images", string.format("html/images/%s.png", item)) + local webpPath = LoadResourceFile("inventory_images", string.format("html/images/%s.webp", item)) + local imagePath = pngPath and string.format("nui://inventory_images/html/images/%s.png", item) or webpPath and string.format("nui://inventory_images/html/images/%s.webp", item) + return imagePath or "https://avatars.githubusercontent.com/u/47620135" +end \ No newline at end of file diff --git a/modules/inventory/tgiann-inventory/server.lua b/modules/inventory/tgiann-inventory/server.lua new file mode 100644 index 0000000..92a9fb0 --- /dev/null +++ b/modules/inventory/tgiann-inventory/server.lua @@ -0,0 +1,63 @@ +if GetResourceState('tgiann-inventory') ~= 'started' then return end +local tgiann = exports["tgiann-inventory"] + +Inventory = Inventory or {} + +Inventory.AddItem = function(src, item, count, slot, metadata) + if not tgiann:CanCarryItem(src, item, count) then return false end + local action = tgiann:AddItem(src, item, count, metadata) + return (action.itemAddRemoveLog == 'added') +end + +Inventory.RemoveItem = function(src, item, count, slot, metadata) + return tgiann:RemoveItem(src, item, count, nil, metadata) +end + +Inventory.GetItem = function(src, item, metadata) + local item = tgiann:GetItemByName(src, item, metadata) + item.count = item.amount + item.metadata = item.info + return item +end + +Inventory.GetItemCount = function(src, item, metadata) + local _item = tgiann:GetItemByName(src, item, metadata) + return _item.amount or 0 +end + +Inventory.GetInventoryItems = function(src) + return tgiann:GetPlayerItems(src) +end + +Inventory.CanCarryItem = function(src, item, count) + return tgiann:CanCarryItem(src, item, count) +end + +Inventory.RegisterStash = function(id, label, slots, weight, owner) + return tgiann:CreateCustomStashWithItem(id, {}) +end + +Inventory.GetItemInfo = function(item) + local itemData = tgiann:GetItemList() + if not itemData[item] then return {} end + local repackedTable = { + name = itemData.name or "Missing Name", + label = itemData.label or "Missing Label", + stack = itemData.unique or "false", + weight = itemData.weight or "0", + description = itemData.description or "none", + image = itemData.image or Inventory.GetImagePath(item), + } + return repackedTable +end + +Inventory.SetMetadata = function(src, item, slot, metadata) + tgiann:UpdateItemMetadata(src, item, slot, metadata) +end + +Inventory.GetImagePath = function(item) + local pngPath = LoadResourceFile("inventory_images", string.format("html/images/%s.png", item)) + local webpPath = LoadResourceFile("inventory_images", string.format("html/images/%s.webp", item)) + local imagePath = pngPath and string.format("nui://inventory_images/html/images/%s.png", item) or webpPath and string.format("nui://inventory_images/html/images/%s.webp", item) + return imagePath or "https://avatars.githubusercontent.com/u/47620135" +end \ No newline at end of file diff --git a/modules/locales/shared.lua b/modules/locales/shared.lua new file mode 100644 index 0000000..7983b10 --- /dev/null +++ b/modules/locales/shared.lua @@ -0,0 +1,59 @@ +local ConvarLang = GetConvar("lang", "none") +local OXLang = GetConvar("ox:locale", "none") +local QBXLang = GetConvar("qb_locale", "none") +local txLang = GetConvar("txAdmin-locale", "none") +local esxLang = GetConvar("esx:locale", "none") + +BridgeSharedConfig = Require("settings/sharedConfig.lua") + +Lang = ConvarLang ~= "none" and +ConvarLang or BridgeSharedConfig.Lang ~= "auto" and BridgeSharedConfig.Lang or +OXLang ~= "none" and OXLang or +QBXLang ~= "none" and QBXLang or +txLang ~= "none" and txLang or +esxLang ~= "none" and esxLang or +"en" + +Language = {} + +function Language.Locale(str, ...) + local resource = GetInvokingResource() or GetCurrentResourceName() + assert(resource, "Resource name not found") + --print(resource, "locales/" .. Lang .. ".json") + local locales = LoadResourceFile(resource, "locales/" .. Lang .. ".json") + --print(locales, Lang) + locales = locales and json.decode(locales) or {} + local locale = locales[str] + + if not locale then + warn("Locale not found for language: " .. Lang) + return str + end + + local args = {...} + if #args > 0 then + for i = 1, #args do + locale = locale:gsub('{' .. i .. '}', args[i]) + end + end + + return locale +end + +if BridgeSharedConfig.DebugLevel == 3 then + -- if outside this resource, use local whatever = Require("modules/locales/shared.lua") + -- whatever.Locales("some-index-in-language-.json-file") + -- Files must be stored in "locales" folder, within the resource. + -- Instead of using Require you can also import it via the manifest. + -- The Lang variable is available globally, which tells you what the server is using. + --print("Language: ", Lang) + --print("Locale: ", Language.Locale("locale-unit-test")) + + -- Example outside community bridge resource: + + -- local Language = Require('modules/locales/shared.lua') + -- print("Language: ", Lang) + -- print("Locale: ", Language.Locale("locale-unit-test")) +end + +return Language \ No newline at end of file diff --git a/modules/managment/Renewed-Banking/server.lua b/modules/managment/Renewed-Banking/server.lua new file mode 100644 index 0000000..c030fc2 --- /dev/null +++ b/modules/managment/Renewed-Banking/server.lua @@ -0,0 +1,14 @@ +if GetResourceState('Renewed-Banking') ~= 'started' then return end +Managment = {} + +Managment.GetAccountMoney = function(account) + return exports['Renewed-Banking']:getAccountMoney(account) +end + +Managment.AddAccountMoney = function(account, amount) + return exports['Renewed-Banking']:addAccountMoney(account, amount) +end + +Managment.RemoveAccountMoney = function(account, amount) + return exports['Renewed-Banking']:removeAccountMoney(account, amount) +end \ No newline at end of file diff --git a/modules/managment/okokBanking/server.lua b/modules/managment/okokBanking/server.lua new file mode 100644 index 0000000..6e3934e --- /dev/null +++ b/modules/managment/okokBanking/server.lua @@ -0,0 +1,14 @@ +if GetResourceState('okokBanking') ~= 'started' then return end +Managment = {} + +Managment.GetAccountMoney = function(account) + return exports['okokBanking']:GetAccount(account) +end + +Managment.AddAccountMoney = function(account, amount) + return exports['okokBanking']:AddMoney(account, amount) +end + +Managment.RemoveAccountMoney = function(account, amount) + return exports['okokBanking']:RemoveMoney(account, amount) +end \ No newline at end of file diff --git a/modules/managment/qb-banking/server.lua b/modules/managment/qb-banking/server.lua new file mode 100644 index 0000000..8a7a640 --- /dev/null +++ b/modules/managment/qb-banking/server.lua @@ -0,0 +1,14 @@ +if GetResourceState('qb-banking') ~= 'started' then return end +Managment = {} + +Managment.GetAccountMoney = function(account) + return exports['qb-banking']:GetAccountBalance(account) +end + +Managment.AddAccountMoney = function(account, amount) + return exports['qb-banking']:AddMoney(account, amount) +end + +Managment.RemoveAccountMoney = function(account, amount) + return exports['qb-banking']:RemoveMoney(account, amount) +end \ No newline at end of file diff --git a/modules/math/computation.lua b/modules/math/computation.lua new file mode 100644 index 0000000..1e6ef28 --- /dev/null +++ b/modules/math/computation.lua @@ -0,0 +1,68 @@ + +---@class Math +------@field public name string @add name field to class Car, you'll see it in code completion +Math = {} + +--- If the value is less than the minimum, it will return the minimum. +--- If the value is greater than the maximum, it will return the maximum. +--- Otherwise, it will return the value. +---@param value number: The value to clamp. +---@param min number: The minimum value. +---@param max number: The maximum value. +---@return number: The clamped value. +function Math.Clamp(value, min, max) + if value < min then + return min + elseif value > max then + return max + else + return value + end +end + +--- Rounds a number to the nearest whole number. +---@param value number: The value to round. +---@return number: The rounded value. +function Math.Round(value) + return math.floor(value + 0.5) +end + +function Math.Truncate(value, decimals) + local mul = decimals and (10 ^ decimals) or 1 + if value < 0 then + return math.ceil(value * mul) / mul + else + return math.floor(value * mul) / mul + end +end + +--- Warps the number around from max to min and vice versa. +---@param value number: The value to wrap. +---@param min number: The minimum value. +---@param max number: The maximum value. +---@return number: The wrapped value. +function Math.Wrap(value, min, max) + local range = max - min + return (value - min) % range + min +end + +--- Gets an interpolated value between two numbers. +---@see https://en.wikipedia.org/wiki/Smoothstep +---@param value number The interpolation value. +---@param min number : The minimum value. +---@param max number : The maximum value. +---@return number The interpolated value. +function Math.Smooth(value, min, max) + value = Math.Clamp((value - min) / (max - min), 0, 1) + return value * value * (3 - 2 * value) +end + +--- Maps a value from one range to another. +---@param value number The value to map. +---@param inMin number The minimum value for the provided value. +---@param inMax number The maximum value for the provided value. +---@param outMin number The minimum value for the output. +---@param outMax number The maximum value for the output. +function Math.Map(value, inMin, inMax, outMin, outMax) + return (value - inMin) / (inMax - inMin) * (outMax - outMin) + outMin +end diff --git a/modules/menu/client.lua b/modules/menu/client.lua new file mode 100644 index 0000000..dc3ff8a --- /dev/null +++ b/modules/menu/client.lua @@ -0,0 +1,207 @@ +local Menus = {} +Menu = {} + +if GetResourceState('ox_lib') ~= 'started' and GetResourceState('qb-menu') ~= 'started' then return end + +--- Converts a QB menu to an Ox menu. +---@param id string The menu ID. +---@param menu table The QB menu data. +---@return table The Ox menu data. +function QBToOxMenu(id, menu) + local oxMenu = { + id = id, + title = "", + canClose = true, + options = {}, + } + for i, v in pairs(menu) do + if v.isMenuHeader then + if oxMenu.title == "" then + oxMenu.title = v.header + end + else + local option = { + title = v.header, + description = v.txt, + icon = v.icon, + args = v.params.args, + onSelect = function(selected, secondary, args) + local params = menu[id]?.options?[selected]?.params + if not params then return end + local event = params.event + local isServer = params.isServer + if not event then return end + if isServer then + return TriggerServerEvent(event, args) + end + return TriggerEvent(event, args) + end + + } + table.insert(oxMenu.options, option) + end + end + return oxMenu +end + +--- Converts an Ox menu to a QB menu. +---@param id string The menu ID. +---@param menu table The Ox menu data. +---@return table The QB menu data. +function OxToQBMenu(id, menu) + local qbMenu = { + { + header = menu.title, + isMenuHeader = true, + } + } + for i, v in pairs(menu.options) do + local button = { + header = v.title, + txt = v.description, + icon = v.icon, + } + + if v.onSelect and type(v.onSelect) == 'function' then + button.params = { + event = "community_bridge:client:MenuCallback", + args = {id = id, selected = i, args = v.args, onSelect = v.onSelect}, + } + end + table.insert(qbMenu, button) + end + return qbMenu +end + +--- Opens a menu based on the configuration. +---@param data table The menu data. +---@param useQb boolean Whether to use QB menu syntax. +---@return id string The menu ID. +function Menu.Open(data, useQb) + --local id = data.id or CreateUniqueId(Menus) + local id = data.id or Ids.CreateUniqueId(Menus, nil, nil) + local menuExists = Menus[id] + if useQb then + if BridgeClientConfig.MenuSystem == "ox" then + if not menuExists then + Menus[id] = QBToOxMenu(id, data) + lib.registerContext(Menus[id]) + end + return lib.showContext(id) + elseif BridgeClientConfig.MenuSystem == "qb" then + Menus[id] = data + return exports['qb-menu']:openMenu(Menus[id]) + end + else + if BridgeClientConfig.MenuSystem == "ox" then + if not menuExists then + Menus[id] = data + lib.registerContext(Menus[id]) + end + return lib.showContext(id) + elseif BridgeClientConfig.MenuSystem == "qb" then + Menus[id] = OxToQBMenu(id, data) + return exports['qb-menu']:openMenu(Menus[id]) + end + end + return id +end + +--- Event to handle callback from menu selection. +--- @param _args table The arguments passed to the callback. +--- @return nil +RegisterNetEvent('community_bridge:client:MenuCallback', function(_args) + local id = _args.id + local onSelect = _args.onSelect + local args = _args.args + if not Menus[id] then return end + onSelect({number=_args.selected}, false, args) +end) + + +--[[ + +--Unit Tests +local qbMenu = { + { + header = 'QBCore Test Menu', + icon = 'fas fa-code', + isMenuHeader = true, -- Set to true to make a nonclickable title + }, + { + header = 'First Button', + txt = 'Open a secondary menu!', + icon = 'fas fa-code-pull-request', + -- disabled = false, -- optional, non-clickable and grey scale + -- hidden = true, -- optional, hides the button completely + params = { + -- isServer = false, -- optional, specify event type + event = 'community_bridge:client:TestEvent', + args = { + number = 1, + } + } + }, + { + header = 'Second Button', + txt = 'Open a secondary menu!', + icon = 'fas fa-code-pull-request', + params = { + event = 'community_bridge:client:TestEvent', + args = { + number = 2, + } + } + } +} + +local oxMenu = { + id = "test", + title = "Test Menu", + options = { + { + title = "First Button", + description = "Open a secondary menu!", + icon = "fas fa-code-pull-request", + args = { + number = 1, + }, + onSelect = function(selected, secondary, args) + print("Selected", json.encode(selected)) + end + }, + { + title = "Second Button", + description = "Open a secondary menu!", + icon = "fas fa-code-pull-request", + args = { + number = 2, + }, + onSelect = function(selected, secondary, args) + print("Selected", json.encode(selected)) + end + } + } +} + +RegisterCommand("testmenu-qbtoox", function() + Menu.Open(qbMenu, true) +end) + +RegisterCommand("testmenu-oxtoqb", function() + Menu.Open(oxMenu, false) +end) + +RegisterCommand("testmenu-oxtoox", function() + Menu.Open(oxMenu, false) +end) + +RegisterCommand("testmenu-qbtoqb", function() + Menu.Open(qbMenu, true) +end) + +RegisterNetEvent('community_bridge:client:TestEvent', function(args) + print("Test Event", json.encode(args)) +end) + +--]] \ No newline at end of file diff --git a/modules/notify/client.lua b/modules/notify/client.lua new file mode 100644 index 0000000..1995499 --- /dev/null +++ b/modules/notify/client.lua @@ -0,0 +1,70 @@ +Notify = Notify or {} + +Notify.SendNotify = function(message, type, time) + if BridgeClientConfig == nil or BridgeClientConfig.NotifySystem == nil then return Prints.error("You have not configured a compatable notify in community_bridge") end + local notifyType = BridgeClientConfig.NotifySystem + time = time or 3000 + if notifyType == 'qb' then + return TriggerEvent('QBCore:Notify', message, 'primary', time) + elseif notifyType == 'mythic_notify' then + return exports['mythic_notify']:SendAlert('inform', message, time) + elseif notifyType == 'pNotify' then + return exports['pNotify']:SendNotification({ text = message, type = type, timeout = time, layout = 'centerRight' }) + elseif notifyType == 'esx_notify' then + return ESX.ShowNotification(message, type, time) + elseif notifyType == 'ox' then + return exports.ox_lib:notify({ description = message, type = type, position = 'center-left' }) + elseif notifyType == 't-notify' then + return exports['t-notify']:Alert({ style = 'info', message = message, duration = time, }) + elseif notifyType == 'wasabi_notify' then + return exports.wasabi_notify:notify(type, message, time, type) + elseif notifyType == 'lab' then + return exports['swe-notify']:SendNotification(message, time, type) + elseif notifyType == 'custom' then + return Prints.Error("You have not set up a custom notify in community_bridge") + else + return Prints.Error("You have not configured a notify in community_bridge") + end +end + +Notify.ShowHelpText = function(message, _position) + if BridgeClientConfig == nil or BridgeClientConfig.ShowHelpText == nil then return Prints.error("You have not configured a compatable helptext in community_bridge") end + local helptextType = BridgeClientConfig.ShowHelpText + if helptextType == 'ox' then + if _position == nil then _position = 'left-center' end + return exports.ox_lib:showTextUI(message, { position = _position }) + elseif helptextType == 'jg' then + return exports['jg-textui']:DrawText(message) + elseif helptextType == 'qb' then + if _position == nil then _position = 'left' end + return exports['qb-core']:DrawText(message, 'left') + elseif helptextType == 'lab' then + return exports['lab-HintUI']:Show(message, "Hint Text") + elseif helptextType == 'custom' then + return Prints.Error("You have not set up a custom ShowHelpText in community_bridge") + else + return Prints.Error("You have not configured a ShowHelpText in community_bridge") + end +end + +Notify.HideHelpText = function() + if BridgeClientConfig == nil or BridgeClientConfig.ShowHelpText == nil then return Prints.error("You have not configured a compatable helptext in community_bridge") end + local helptextType = BridgeClientConfig.ShowHelpText + if helptextType == 'ox' then + return exports.ox_lib:hideTextUI() + elseif helptextType == 'jg' then + return exports['jg-textui']:HideText() + elseif helptextType == 'qb' then + return exports['qb-core']:HideText() + elseif helptextType == 'lab' then + return exports['lab-HintUI']:Hide() + elseif helptextType == 'custom' then + return Prints.Error("You have not set up a custom HideHelpText in community_bridge") + else + return Prints.Error("You have not configured a HideHelpText in community_bridge") + end +end + +RegisterNetEvent('community_bridge:Client:Notify', function(message, _type, time) + Notify.SendNotify(message, _type, time) +end) \ No newline at end of file diff --git a/modules/notify/server.lua b/modules/notify/server.lua new file mode 100644 index 0000000..ebf5fbc --- /dev/null +++ b/modules/notify/server.lua @@ -0,0 +1,5 @@ +Notify = Notify or {} + +Notify.SendNotify = function(src, message, _type, time) + TriggerClientEvent('community_bridge:Client:Notify', src, message, _type, time) +end \ No newline at end of file diff --git a/modules/phone/_defualts/client.lua b/modules/phone/_defualts/client.lua new file mode 100644 index 0000000..8b33ca9 --- /dev/null +++ b/modules/phone/_defualts/client.lua @@ -0,0 +1,5 @@ +Phone = Phone or {} + +Phone.SendEmail = function(email, title, message) + return false, Print.Error('There Is No Phone Bridged.') +end \ No newline at end of file diff --git a/modules/phone/_defualts/server.lua b/modules/phone/_defualts/server.lua new file mode 100644 index 0000000..a367380 --- /dev/null +++ b/modules/phone/_defualts/server.lua @@ -0,0 +1,9 @@ +Phone = Phone or {} + +Phone.GetPlayerPhone = function(src) + return false, Print.Error('There Is No Phone Bridged.') +end + +Phone.SendEmail = function(src, email, title, message) + return false, Print.Error('There Is No Phone Bridged.') +end \ No newline at end of file diff --git a/modules/phone/gksphone/client.lua b/modules/phone/gksphone/client.lua new file mode 100644 index 0000000..ea45267 --- /dev/null +++ b/modules/phone/gksphone/client.lua @@ -0,0 +1,6 @@ +if GetResourceState('gksphone') ~= 'started' then return end +Phone = {} + +Phone.SendEmail = function(email, title, message) + return exports["gksphone"]:SendNewMail({ sender = email, image = '/html/static/img/icons/mail.png', subject = title, message = message }) +end \ No newline at end of file diff --git a/modules/phone/gksphone/server.lua b/modules/phone/gksphone/server.lua new file mode 100644 index 0000000..5de2c37 --- /dev/null +++ b/modules/phone/gksphone/server.lua @@ -0,0 +1,16 @@ +if GetResourceState('gksphone') ~= 'started' then return end +Phone = {} + +Phone.GetPlayerPhone = function(src) + return exports["gksphone"]:GetPhoneBySource(src) or false +end + +Phone.SendEmail = function(src, email, title, message) + local data = {} + data.sender = email + data.image = '/html/static/img/icons/mail.png' + data.subject = title + data.message = message + exports["gksphone"]:SendNewMail(src, data) + return true +end \ No newline at end of file diff --git a/modules/phone/lb-phone/client.lua b/modules/phone/lb-phone/client.lua new file mode 100644 index 0000000..5918f64 --- /dev/null +++ b/modules/phone/lb-phone/client.lua @@ -0,0 +1,6 @@ +if GetResourceState('lb-phone') ~= 'started' then return end +Phone = {} + +Phone.SendEmail = function(email, title, message) + TriggerServerEvent('community_bridge:Server:genericEmail', {email = email, title = title, message = message}) +end \ No newline at end of file diff --git a/modules/phone/lb-phone/server.lua b/modules/phone/lb-phone/server.lua new file mode 100644 index 0000000..84cf579 --- /dev/null +++ b/modules/phone/lb-phone/server.lua @@ -0,0 +1,26 @@ +if GetResourceState('lb-phone') ~= 'started' then return end +Phone = {} + +Phone.GetPlayerPhone = function(src) + return exports["lb-phone"]:GetEquippedPhoneNumber(src) or false +end + +Phone.SendEmail = function(src, email, title, message) + local numberNumber = exports["lb-phone"]:GetEquippedPhoneNumber(src) + if not numberNumber then return false, Prints.Error("Could not Find Phone number") end + local playerEmail = exports["lb-phone"]:GetEmailAddress(numberNumber) + if not playerEmail then return false, Prints.Error("Could not Find email") end + local success, id = exports["lb-phone"]:SendMail({ + to = playerEmail, + sender = email, + subject = title, + message = message, + }) + return success +end + +RegisterNetEvent('community_bridge:Server:genericEmail', function(data) + local src = source + Prints.Debug('community_bridge:Server:genericEmail Hit') + return Phone.SendEmail(src, data.email, data.title, data.message) +end) \ No newline at end of file diff --git a/modules/phone/qs-smartphone/client.lua b/modules/phone/qs-smartphone/client.lua new file mode 100644 index 0000000..b325b24 --- /dev/null +++ b/modules/phone/qs-smartphone/client.lua @@ -0,0 +1,11 @@ +if GetResourceState('qs-smartphone') ~= 'started' then return end +Phone = {} + +Phone.SendEmail = function(email, title, message) + return TriggerServerEvent('qs-smartphone:server:sendNewMail', { sender = email, subject = title, message = message, button = {} }) +end + +RegisterNetEvent('community_bridge:Server:genericEmail', function(data) + TriggerServerEvent('qs-smartphone:server:sendNewMail', { sender = data.email, subject = data.title, message = data.message, button = {} }) + return true +end) \ No newline at end of file diff --git a/modules/phone/qs-smartphone/server.lua b/modules/phone/qs-smartphone/server.lua new file mode 100644 index 0000000..909ee8d --- /dev/null +++ b/modules/phone/qs-smartphone/server.lua @@ -0,0 +1,11 @@ +if GetResourceState('qs-smartphone') ~= 'started' then return end +Phone = {} + +Phone.GetPlayerPhone = function(src) + return exports['qs-base']:GetPlayerPhone(src) or false +end + +Phone.SendEmail = function(src, email, title, message) + TriggerClientEvent('community_bridge:Server:genericEmail', src, { sender = email, subject = title, message = message, button = {} }) + return true +end \ No newline at end of file diff --git a/modules/progressbar/ox_lib/client.lua b/modules/progressbar/ox_lib/client.lua new file mode 100644 index 0000000..50efeef --- /dev/null +++ b/modules/progressbar/ox_lib/client.lua @@ -0,0 +1,38 @@ +if BridgeClientConfig.ProgressBar ~= "ox" then return end +Progressbar = {} +local _progBarType = BridgeClientConfig.ProgressBarStyle or "bar" + +Progressbar.StartProgressBar = function(time, label, whiledead, cancancel, disable, animTable, successAction, canceledAction) + local runTime = time or 10000 + local textLabel = label or "Doing something" + local deadBool = whiledead or false + local cancelBool = cancancel or false + local disableKeys = disable or { move = true, sprint = true, car = true, combat = true, } + local anim = animTable or nil + local success = successAction or function() Prints.Debug("Success") end + local canceled = canceledAction or function() Prints.Debug("Cancelled") end + if _progBarType == "bar" then + if exports.ox_lib:progressBar({ + duration = runTime, + label = textLabel, + useWhileDead = deadBool, + canCancel = cancelBool, + disable = disableKeys, + anim = anim, + }) then success() else canceled() end + elseif _progBarType == "circle" then + if exports.ox_lib:progressCircle({ + duration = runTime, + label = textLabel, + position = 'bottom', + useWhileDead = deadBool, + canCancel = cancelBool, + disable = disableKeys, + anim = anim, + }) then success() else canceled() end + end +end + +Progressbar.IsProgressBarActive = function() + return exports.ox_lib:progressActive() +end \ No newline at end of file diff --git a/modules/progressbar/qb-progressbar/client.lua b/modules/progressbar/qb-progressbar/client.lua new file mode 100644 index 0000000..a9df93f --- /dev/null +++ b/modules/progressbar/qb-progressbar/client.lua @@ -0,0 +1,60 @@ +if BridgeClientConfig.ProgressBar ~= "qb" then return end +Progressbar = {} + +local function convertOxToQB(disabledTable, animTable) + local repackedTable = { disabled = {}, animations = {}} + for _, v in pairs(disabledTable) do + if v.move then + repackedTable.disabled.disableMovement = v.move + end + if v.car then + repackedTable.disabled.disableCarMovement = v.car + end + if v.combat then + repackedTable.disabled.disableCombat = v.combat + end + if v.mouse then + repackedTable.disabled.disableMouse = v.mouse + end + end + for _, v in pairs(animTable) do + if v.dict then + repackedTable.animations.animDict = v.animDict + end + if v.clip then + repackedTable.animations.anim = v.anim + end + end + return repackedTable +end + +Progressbar.StartProgressBar = function(time, label, whiledead, cancancel, disable, animTable, successAction, canceledAction) + local runTime = time or 10000 + local textLabel = label or "Doing something" + local deadBool = whiledead or false + local cancelBool = cancancel or false + local success = successAction or function() Prints.Debug("Success") end + local canceled = canceledAction or function() Prints.Debug("Cancelled") end + local repackedTable = convertOxToQB(disable, animTable) + exports['progressbar']:Progress({ + name = textLabel, + duration = runTime, + label = textLabel, + useWhileDead = deadBool, + canCancel = cancelBool, + controlDisables = repackedTable.disabled, + animation = repackedTable.animations, + prop = {}, + propTwo = {} + }, function(cancelled) + if not cancelled then + success() + else + canceled() + end + end) +end + +Progressbar.IsProgressBarActive = function() + return exports["progressbar"]:isDoingSomething() +end \ No newline at end of file diff --git a/modules/target/ox_target/client.lua b/modules/target/ox_target/client.lua new file mode 100644 index 0000000..4490a67 --- /dev/null +++ b/modules/target/ox_target/client.lua @@ -0,0 +1,72 @@ +if GetResourceState('ox_target') ~= 'started' then return end + +local targetDebug = false +local function detectDebugEnabled() + if BridgeClientConfig.DebugLevel == 3 then + targetDebug = true + end +end + +detectDebugEnabled() + +local ox_target = exports.ox_target +local targetZones = {} + +Target = {} + +Target.AddGlobalPlayer = function(options) + ox_target:addGlobalPlayer(options) +end + +Target.AddLocalEntity = function(entities, options) + ox_target:addLocalEntity(entities, options) +end + +Target.AddModel = function(models, options) + ox_target:addModel(models, options) +end + +Target.AddBoxZone = function(name, coords, size, heading, options) + local target = ox_target:addBoxZone({ + coords = coords, + size = size, + rotation = heading, + debug = targetDebug, + options = options, + }) + table.insert(targetZones, { name = name, id = target, creator = GetInvokingResource() }) + return target +end + +Target.RemoveGlobalPlayer = function() + ox_target:removeGlobalPlayer() +end + +Target.RemoveLocalEntity = function(entity) + ox_target:removeLocalEntity(entity) +end + +Target.RemoveModel = function(model) + ox_target:removeModel(model) +end + +Target.RemoveZone = function(name) + for _, data in pairs(targetZones) do + if data.name == name then + ox_target:removeZone(data.id) + table.remove(targetZones, _) + break + end + end +end + +AddEventHandler('onResourceStop', function(resource) + if resource == GetCurrentResourceName() then + for _, target in pairs(targetZones) do + if target.creator == resource then + ox_target:removeZone(target.id) + end + end + targetZones = {} + end +end) diff --git a/modules/target/qb-target/client.lua b/modules/target/qb-target/client.lua new file mode 100644 index 0000000..f329e75 --- /dev/null +++ b/modules/target/qb-target/client.lua @@ -0,0 +1,94 @@ +if GetResourceState('qb-target') ~= 'started' or GetResourceState('ox_target') == 'started' then return end + +local targetDebug = false +local function detectDebugEnabled() + if BridgeClientConfig.DebugLevel == 3 then + targetDebug = true + end +end + +detectDebugEnabled() + +local targetZones = {} + +Target = {} + +Target.AddGlobalPlayer = function(options) + for k, v in pairs(options) do + options[k].action = v.onSelect + end + exports['qb-target']:AddGlobalPlayer({ + options = options, + distance = options.distance or 1.5 + }) +end + +Target.AddLocalEntity = function(entities, options) + for k, v in pairs(options) do + options[k].action = v.onSelect + end + exports['qb-target']:AddTargetEntity(entities, { + options = options, + distance = options.distance or 1.5 + }) +end + +Target.AddModel = function(models, options) + for k, v in pairs(options) do + options[k].action = v.onSelect + end + exports['qb-target']:AddTargetModel(models, { + options = options, + distance = options.distance or 1.5, + }) +end + +Target.AddBoxZone = function(name, coords, size, heading, options) + for k, v in pairs(options) do + options[k].action = v.onSelect + end + exports['qb-target']:AddBoxZone(name, coords, size.x, size.y, { + name = name, + debugPoly = targetDebug, + heading = heading, + minZ = coords.z - (size.x * 0.5), + maxZ = coords.z + (size.x * 0.5), + }, { + options = options, + distance = options.distance or 1.5, + }) + table.insert(targetZones, { name = name, creator = GetInvokingResource() }) +end + +Target.RemoveGlobalPlayer = function() + exports['qb-target']:RemoveGlobalPlayer() +end + +Target.RemoveLocalEntity = function(entity) + exports['qb-target']:RemoveTargetEntity(entity) +end + +Target.RemoveModel = function(model) + exports['qb-target']:RemoveTargetModel(model) +end + +Target.RemoveZone = function(name) + for _, data in pairs(targetZones) do + if data.name == name then + exports['qb-target']:RemoveZone(name) + table.remove(targetZones, _) + break + end + end +end + +AddEventHandler('onResourceStop', function(resource) + if resource == GetCurrentResourceName() then + for _, target in pairs(targetZones) do + if target.creator == resource then + exports['qb-target']:RemoveZone(target.name) + end + end + targetZones = {} + end +end) \ No newline at end of file diff --git a/modules/utility/client/object_Placer.lua b/modules/utility/client/object_Placer.lua new file mode 100644 index 0000000..f2a4ddc --- /dev/null +++ b/modules/utility/client/object_Placer.lua @@ -0,0 +1,109 @@ +Utility = Utility or {} + +local activePlacementProp = nil +lib.locale() + +-- Object placer -- +local placementText = { + locale('place_object'), + locale('place_object_place'), + locale('place_object_cancel'), + locale('place_object_scroll_up'), + locale('place_object_scroll_down') +} + +local function finishPlacing() + Bridge.notify.HideHelpText() + if activePlacementProp == nil then return end + DeleteObject(activePlacementProp) + activePlacementProp = nil +end + +Utility.PlaceObject = function(object, distance, snapToGround, allowedMats, offset) + if activePlacementProp then return end + + if not object then Prints.Error('no_prop_defined') end + + local propObject = type(object) == 'string' and joaat(object) or object + local heading = 0.0 + local checkDist = distance or 10.0 + + Utility.LoadModel(propObject) + + activePlacementProp = CreateObject(propObject, 1.0, 1.0, 1.0, false, true, true) + SetModelAsNoLongerNeeded(propObject) + SetEntityAlpha(activePlacementProp, 150, false) + SetEntityCollision(activePlacementProp, false, false) + SetEntityInvincible(activePlacementProp, true) + FreezeEntityPosition(activePlacementProp, true) + + Bridge.notify.ShowHelpText(type(placementText) == 'table' and table.concat(placementText) or placementText, { + position = "left-center", + }) + + local outLine = false + + while activePlacementProp do + --local hit, _, coords, _, materialHash = lib.raycast.fromCamera(1, 4) + --local hit, _, coords, _, materialHash = lib.raycast.fromCamera(1, 4, nil) + local hit, _, coords, _, materialHash = lib.raycast.fromCamera(1, 4) + if hit then + if offset then + coords += offset + end + + SetEntityCoords(activePlacementProp, coords.x, coords.y, coords.z, false, false, false, false) + local distCheck = #(GetEntityCoords(cache.ped) - coords) + SetEntityHeading(activePlacementProp, heading) + + if snapToGround then + PlaceObjectOnGroundProperly(activePlacementProp) + end + + if outLine then + outLine = false + SetEntityDrawOutline(activePlacementProp, false) + end + + if (allowedMats and not allowedMats[materialHash]) or distCheck >= checkDist then + if not outLine then + outLine = true + SetEntityDrawOutline(activePlacementProp, true) + end + end + + if IsControlJustReleased(0, 38) then + if not outLine and (not allowedMats or allowedMats[materialHash]) and distCheck < checkDist then + finishPlacing() + + return coords, heading + end + end + + if IsControlJustReleased(0, 73) then + finishPlacing() + + return nil, nil + end + + if IsControlJustReleased(0, 14) then + heading = heading + 5 + if heading > 360 then heading = 0.0 end + end + + if IsControlJustReleased(0, 15) then + heading = heading - 5 + if heading < 0 then + heading = 360.0 + end + end + end + end +end + +Utility.StopPlacing = function() + if not activePlacementProp then return end + finishPlacing() +end + +-- This is derrived and slightly altered from its creator and licensed under GPL-3.0 license Author:Zoo, the original is located here https://github.com/Renewed-Scripts/Renewed-Lib/tree/main \ No newline at end of file diff --git a/modules/utility/client/utility.lua b/modules/utility/client/utility.lua new file mode 100644 index 0000000..4cc1e60 --- /dev/null +++ b/modules/utility/client/utility.lua @@ -0,0 +1,288 @@ +Utility = Utility or {} +local blipIDs = {} +local spawnedPeds = {} +local ActivePoints = {} +lib.locale() + +Utility.CreateVehicle = function(model, coords, heading, networked) + if networked == nil then networked = true end + Utility.LoadModel(model) + if not HasModelLoaded(model) then return Prints.Error("Model Has Not Loaded") end + local vehicle = CreateVehicle(model, coords.x, coords.y, coords.z, heading, networked, false) + SetVehicleHasBeenOwnedByPlayer(vehicle, true) + SetVehicleNeedsToBeHotwired(vehicle, false) + SetModelAsNoLongerNeeded(model) + SetVehRadioStation(vehicle, "OFF") + return vehicle, { networkid = NetworkGetNetworkIdFromEntity(vehicle) or 0, coords = GetEntityCoords(vehicle), heading = GetEntityHeading(vehicle), } +end + +Utility.StartBusySpinner = function(text) + AddTextEntry(text, text) + BeginTextCommandBusyString(text) + AddTextComponentSubstringPlayerName(text) + EndTextCommandBusyString(0) +end + +Utility.StopBusySpinner = function() + if BusyspinnerIsOn() then BusyspinnerOff() end +end + +Utility.CreateProp = function(model, coords, heading, networked) + if networked == nil then networked = true end + Utility.LoadModel(model) + if not HasModelLoaded(model) then return Prints.Error("Model Has Not Loaded") end + local propEntity = CreateObject(model, coords.x, coords.y, coords.z, networked, false, false) + SetEntityHeading(propEntity, heading) + SetModelAsNoLongerNeeded(model) + return propEntity +end + +Utility.CreateBlip = function(coords, sprite, color, scale, label, shortRange) + local blip = AddBlipForCoord(coords.x, coords.y, coords.z) + SetBlipSprite(blip, sprite or 8) + SetBlipColour(blip, color or 3) + SetBlipScale(blip, scale or 0.8) + SetBlipAsShortRange(blip, shortRange) + AddTextEntry(label, label) + BeginTextCommandSetBlipName(label) + EndTextCommandSetBlipName(blip) + table.insert(blipIDs, blip) + return blip +end + +Utility.RemoveBlip = function(blip) + local success = false + for i, storedBlip in ipairs(blipIDs) do + if storedBlip == blip then + RemoveBlip(blip) + table.remove(blipIDs, i) + success = true + break + end + end + return success +end + +Utility.LoadModel = function(model) + if type(model) ~= 'number' then model = joaat(model) end + if not IsModelValid(model) and not IsModelInCdimage(model) then return false end + RequestModel(model) + local count = 0 + while not HasModelLoaded(model) and count < 30000 do + Wait(0) + count = count + 1 + end + return HasModelLoaded(model) +end + +Utility.CreatePed = function(model, coords, heading, networked, clothing) + if networked == nil then networked = true end + Utility.LoadModel(model) + if not HasModelLoaded(model) then return Prints.Error("Model Has Not Loaded") end + local spawnedEntity = CreatePed(0, model, coords.x, coords.y, coords.z, heading, networked, false) + if clothing then + for componentID, v in pairs(clothing) do + SetPedComponentVariation(spawnedEntity, componentID, v[1], v[2], 0) + end + end + FreezeEntityPosition(spawnedEntity, true) + SetEntityInvincible(spawnedEntity, true) + SetBlockingOfNonTemporaryEvents(spawnedEntity, true) + SetModelAsNoLongerNeeded(model) + table.insert(spawnedPeds, spawnedEntity) + return spawnedEntity +end + +Utility.RemovePed = function(entity) + local success = false + DeleteEntity(entity) + for i, storedEntity in ipairs(spawnedPeds) do + if storedEntity == entity then + table.remove(spawnedPeds, i) + success = true + break + end + end + return success +end + +Utility.NativeInputMenu = function(text, length) + local maxLength = Math.Clamp(length, 1, 50) + local menutText = text or 'enter text' + AddTextEntry(menutText, menutText) + DisplayOnscreenKeyboard(1, menutText, "", "", "", "", "", maxLength) + while(UpdateOnscreenKeyboard() == 0) do + DisableAllControlActions(0) + Wait(0) + end + if(GetOnscreenKeyboardResult()) then + local result = GetOnscreenKeyboardResult() + return result + end + return false +end + +Utility.GetEntitySkinData = function(entity) + local skinData = {} + skinData.clothing = {} + for i = 0, 11 do + skinData.clothing[i] = {GetPedDrawableVariation(entity, i), GetPedTextureVariation(entity, i)} + end + return skinData +end + +Utility.SetEntitySkinData = function(entity, skinData) + for i = 0, 11 do + SetPedComponentVariation(entity, i, skinData.clothing[i][1], skinData.clothing[i][2], 0) + end + return true +end + +Utility.NativeAlert = function(data) + local message = data.message or 'No message provided' + local coords = data.coords or GetEntityCoords(cache.ped) + local job = data.job + local scale = data.scale or 0.8 + local sprite = data.sprite or 1 + TriggerServerEvent('community_bridge:server:alert', {message = message, coords = coords, job = job, scale = scale, sprite = sprite}) +end + +Utility.ReloadSkin = function() + local skinData = Utility.GetEntitySkinData(cache.ped) + Utility.SetEntitySkinData(cache.ped, skinData) + for _, props in pairs(GetGamePool("CObject")) do + if IsEntityAttachedToEntity(cache.ped, props) then + SetEntityAsMissionEntity(props, true, true) + DeleteObject(props) + DeleteEntity(props) + end + end + return true +end + +Utility.RestoreAppearance = function(data) + return Utility.SetEntitySkinData(cache.ped, data) +end + +Utility.HelpText = function(text, duration) + AddTextEntry(text, text) + BeginTextCommandDisplayHelp(text) + EndTextCommandDisplayHelp(0, false, true, duration or 5000) +end + +Utility.NotifyText = function(text) + AddTextEntry(text, text) + SetNotificationTextEntry(text) + DrawNotification(false, true) +end + +Utility.TeleportPlayer = function(coords, conditionFunction, afterTeleportFunction) + if conditionFunction ~= nil then + if not conditionFunction() then + return + end + end + DoScreenFadeOut(2500) + Wait(2500) + SetEntityCoords(cache.ped, coords.x, coords.y, coords.z, false, false, false, false) + if coords.w then + SetEntityHeading(cache.ped, coords.w) + end + FreezeEntityPosition(cache.ped, true) + local count = 0 + while not HasCollisionLoadedAroundEntity(cache.ped) and count <= 30000 do + RequestCollisionAtCoord(coords.x, coords.y, coords.z) + Wait(0) + count = count + 1 + end + FreezeEntityPosition(cache.ped, false) + DoScreenFadeIn(1000) + if afterTeleportFunction ~= nil then + afterTeleportFunction() + end +end + +Utility.GetEntityHashFromModel = function(model) + if type(model) ~= 'number' then model = joaat(model) end + return model +end + +Utility.GetClosestPlayer = function(coords, distanceScope, includeMe) + local players = GetActivePlayers() + local closestPlayer = 0 + local selfPed = cache.ped + local selfCoords = coords or GetEntityCoords(cache.ped) + local closestDistance = distanceScope or 5 + + for _, player in ipairs(players) do + local playerPed = GetPlayerPed(player) + if includeMe or playerPed ~= selfPed then + local playerCoords = GetEntityCoords(playerPed) + local distance = #(selfCoords - playerCoords) + if closestDistance == -1 or distance < closestDistance then + closestPlayer = player + closestDistance = distance + end + end + end + + return closestPlayer, closestDistance, GetPlayerServerId(closestPlayer) +end + +-- register points +Utility.RegisterPoint = function(pointCoords, pointDistance, pointOnEnter, pointOnExit) + local enterZone = lib.points.new({ + coords = pointCoords, + distance = pointDistance, + onEnter = function(self) + pointOnEnter(self) + end, + onExit = function(self) + pointOnExit(self) + end, + }) + local pointID = Utility.CreateUniqueId(nil, 5, nil) + ActivePoints[pointID] = enterZone + return enterZone, pointID +end + +-- Function to retrieve the enterZone using pointID +Utility.GetPointById = function(pointID) + return ActivePoints[pointID] +end + +Utility.RemovePoint = function(pointID) + local point = ActivePoints[pointID] + if point then + --print("Removing point with ID " .. pointID) + point:remove() -- Call the remove method on the point (ensure this method stops all event listeners) + ActivePoints[pointID] = nil -- Remove from ActivePoints table + --print("Point removed successfully.") + return true + else + --print("Point with ID " .. pointID .. " not found.") + return false + end +end + +AddEventHandler('onResourceStop', function(resource) + if resource == GetCurrentResourceName() then + for _, blip in pairs(blipIDs) do + if DoesBlipExist(blip.id) then + RemoveBlip(blip.id) + end + end + for _, ped in pairs(spawnedPeds) do + if DoesEntityExist(ped) then + DeleteEntity(ped) + end + end + end +end) + +RegisterNetEvent('community_bridge:client:alert', function(data) + local blip = Utility.CreateBlip(data.coords, data.sprite, 3, data.scale, data.message, true) + SetTimeout(40000, function() + Utility.RemoveBlip(blip) + end) +end) \ No newline at end of file diff --git a/modules/utility/server/VersionChecker.lua b/modules/utility/server/VersionChecker.lua new file mode 100644 index 0000000..9ee14aa --- /dev/null +++ b/modules/utility/server/VersionChecker.lua @@ -0,0 +1,38 @@ +Utility = Utility or {} + +function Utility.VersionChecker(repoPath) + local resource = repoPath:match("([^/]+)$") + if not resource then return Prints.Error('^1Invalid repository format. Expected format: "username/reponame"^0') end + + local version = GetResourceMetadata(resource, "version", 0) + if not version then return Prints.Error(('^1Unable to determine current resource version for %s ^0'):format(resource)) end + + version = version:match('%d+%.%d+%.%d+') + if not version then return Prints.Error(('^1Invalid version format for %s ^0'):format(resource)) end + + local username, reponame = repoPath:match("([^/]+)/([^/]+)") + if not username or not reponame then return Prints.Error('^1Invalid repository format. Expected format: "username/reponame"^0') end + PerformHttpRequest(('https://api.github.com/repos/%s/%s/releases/latest'):format(username, reponame), function(status, response) + local failure = ('^1Unable locate github repo for resource %s ^0'):format(resource) + + if status ~= 200 then return Prints.Error(failure) end + response = json.decode(response) + + if response.prerelease then return Prints.Error(failure) end + + local latest = response.tag_name:match('%d+%.%d+%.%d+') + if not latest then return Prints.Error(failure) end + + if latest == version then return print(('^2 %s is on the latest version.^0'):format(resource)) end + local currentVersion, latestVersion = version:gsub('%D', ''), latest:gsub('%D', '') + + if currentVersion < latestVersion then + return print(('^1An update is available for %s (current version: %s)\r\n - ^5Please download the latest version from the GitHub release page.^7\r\n%s'):format(resource, version, response.html_url)) + end + end, 'GET') +end + +AddEventHandler('onResourceStart', function(resourceName) + if GetCurrentResourceName() ~= resourceName then return end + Utility.VersionChecker("The-Order-Of-The-Sacred-Framework/community_bridge") +end) \ No newline at end of file diff --git a/modules/utility/server/logs.lua b/modules/utility/server/logs.lua new file mode 100644 index 0000000..e8c8d8d --- /dev/null +++ b/modules/utility/server/logs.lua @@ -0,0 +1,50 @@ +Utility = Utility or {} + +local WebhookURL = BridgeServerConfig.WebhookURL +local LogoForEmbed = BridgeServerConfig.WebhookImage + +Utility.SendLog = function(src, message) + if not src or not message then return end + if BridgeServerConfig.LogSystem == "builtin" then + PerformHttpRequest(WebhookURL, function(err, text, headers) end, 'POST', json.encode( + { + username = "Community_Bridge's Logger", + avatar_url = 'https://cdn.discordapp.com/avatars/299410129982455808/31ce635662206e8bd0132c34ce9ce683?size=1024', + embeds = { + { + color = "15769093", + title = GetCurrentResourceName(), + url = 'https://discord.gg/wsPAK5mEPg', + --description = message, + thumbnail = { url = LogoForEmbed }, + fields = { + { + name = '**Player ID**', + value = src, + inline = true, + }, + { + name = '**Player Identifier**', + value = Framework.GetPlayerIdentifier(src), + inline = true, + }, + { + name = 'Log Message', + value = "```"..message.."```", + inline = false, + }, + }, + timestamp = os.date('!%Y-%m-%dT%H:%M:%S'), + footer = { + text = "Community_Bridge | "..GetCurrentResourceName(), + icon_url = 'https://cdn.discordapp.com/avatars/299410129982455808/31ce635662206e8bd0132c34ce9ce683?size=1024', + }, + } + } + }), { ['Content-Type']= 'application/json' }) + elseif BridgeServerConfig.LogSystem == "qb" then + return TriggerEvent('qb-log:server:CreateLog', GetCurrentResourceName(), GetCurrentResourceName(), 'green', message) + elseif BridgeServerConfig.LogSystem == "ox" then + return exports.ox_lib:logger(src, GetCurrentResourceName(), message) + end +end \ No newline at end of file diff --git a/modules/utility/server/lootTables.lua b/modules/utility/server/lootTables.lua new file mode 100644 index 0000000..9244c54 --- /dev/null +++ b/modules/utility/server/lootTables.lua @@ -0,0 +1,70 @@ +Utility = Utility or {} + +local lootTables = {} + +Utility.RegisterLootTable = function(name, items) + local repackedTable = {} + for k, v in pairs(items) do + table.insert(repackedTable, { + name = k, + min = v.min, + max = v.max, + chance = v.chance, + tier = v.tier, + item = v.item, + metadata = v.metadata + }) + end + lootTables[name] = repackedTable + return lootTables[name] +end + +Utility.GetLootTable = function(name) + assert(name, "No Name Passed For Loot Table") + return lootTables[name] or {} +end + +Utility.GetRandomItem = function(name, tier, randomNumber) + assert(name, "No Name Passed For Loot Table") + if tier == nil then tier = 1 end + local lootTable = lootTables[name] or {} + math.randomseed(GetGameTimer()) + local chance = randomNumber or math.random(1, 100) + for _, v in pairs(lootTable) do + if v.chance <= chance and tier == v.tier then + return { item = v.item, metadata = v.metadata, count = math.random(v.min, v.max), tier = v.tier, chance = v.chance} + end + end +end + +Utility.GetRandomItems = function(name, tier, randomNumber) + assert(name, "No Name Passed For Loot Table") + if tier == nil then tier = 1 end + local lootTable = Utility.GetLootTable(name) + math.randomseed(GetGameTimer()) + local chance = randomNumber or math.random(1, 100) + local items = {} + for _, v in pairs(lootTable) do + if v.chance <= chance and tier == v.tier then + table.insert(items,{item = v.item, metadata = v.metadata, count = math.random(v.min, v.max), tier = v.tier, chance = v.chance}) + end + end + return items +end + +Utility.GetRandomItemsWithLimit = function(name, tier, randomNumber) + assert(name, "No Name Passed For Loot Table") + if tier == nil then tier = 1 end + local lootTable = Utility.GetLootTable(name) + math.randomseed(GetGameTimer()) + local chance = randomNumber or math.random(1, 100) + local items = {} + for k = #lootTable, 1, -1 do + local v = lootTable[k] + if chance <= v.chance and tier == v.tier then + table.insert(items, {v.item, v.metadata, math.random(v.min, v.max), v.tier, v.chance}) + table.remove(lootTable, k) + end + end + return items +end \ No newline at end of file diff --git a/modules/utility/server/supplement_events.lua b/modules/utility/server/supplement_events.lua new file mode 100644 index 0000000..fbe2fa1 --- /dev/null +++ b/modules/utility/server/supplement_events.lua @@ -0,0 +1,6 @@ +RegisterServerEvent("community_bridge:server:alert", function(data) + local playersByJob = Framework.GetPlayersByJob(data.job) + for _, src in pairs(playersByJob) do + TriggerClientEvent("community_bridge:client:alert", src, data) + end +end) \ No newline at end of file diff --git a/modules/utility/shared/callbacks.lua b/modules/utility/shared/callbacks.lua new file mode 100644 index 0000000..72977c9 --- /dev/null +++ b/modules/utility/shared/callbacks.lua @@ -0,0 +1,145 @@ +Callbacks = {} +cbData = {} +Callback = Callback or {} + +local resource = GetCurrentResourceName() or 'unknown' + +local clientToServerName = resource .. ':server:CS:TriggerCallback' +local clientToServerBackToClientName = resource .. ':client:CSC:TriggerCallback' + + +local serverToClientName = resource .. ':client:SC:TriggerCallback' +local serverToClientBackToServerName = resource .. ':server:SCS:TriggerCallback' + + +if not IsDuplicityVersion() then goto client end + + + +-- -- -- -- -- -- -- -- -- -- +-- ▄▀▀ ██▀ █▀▄ █ █ ██▀ █▀▄ +-- ▄█▀ █▄▄ █▀▄ ▀▄▀ █▄▄ █▀▄ +-- -- -- -- -- -- -- -- -- -- + + + +-- client to server rebound +function Callback.Register(name, callback, all) + Callback[name] = { + callback = callback, + toAll = all + } +end + +RegisterNetEvent(clientToServerName, function(name, ...) + local src = source + local data = Callback[name] + if not data then return end + local func = data.callback + if not func then return end + local toAll = data.toAll and -1 or src + local cb = function(...) + TriggerClientEvent(clientToServerBackToClientName, toAll, name, ...) + end + func(src, cb, ...) +end) +----------------------------- + +-- server to client rebound + +function Callback.Trigger(name, src, func, ...) + if src == nil then src = -1 end + local p = promise.new() + cbData[name] = {cb = func, p = p} + if type(src) == 'table' then + for i, d in pairs(src) do + TriggerClientEvent(serverToClientName, tonumber(d), name, ...) + end + return Citizen.Await(p) + end + TriggerClientEvent(serverToClientName, tonumber(src), name, ...) + return Citizen.Await(p) +end + +RegisterNetEvent(serverToClientBackToServerName, function(name, ...) + print('Rebound') + local data = cbData[name] + if not data then return end + local func = data.cb + if not func then return end + data.p:resolve(func(...) or true) + cbData[name] = nil +end) +----------------------------- +exports('RegisterCallback', Callback.Register) +exports('TriggerCallback', Callback.Trigger) + + +-- -- -- -- -- -- -- -- -- -- +-- ▄▀▀ █ █ ██▀ █▄ █ ▀█▀ +-- ▀▄▄ █▄▄ █ █▄▄ █ ▀█ █ +-- -- -- -- -- -- -- -- -- -- +if IsDuplicityVersion() then return end +::client:: + + +cbRebounds = {} +function Callback.Register(name, callback, all) + Callback[name] = { + callback = callback, + } +end + + +function Callback.RegisterRebound(name, callback) + cbRebounds[name] = callback +end + + +-- client to server rebound +function Callback.Trigger(name, func, ...) + local p = promise.new() + TriggerServerEvent(clientToServerName, name, ...) + cbData[name] = {cb = func, p = p} + CreateThread(function() + Wait(5000) + if cbData[name] then + cbData[name].p:resolve() + cbData[name] = nil + end + end) + print('Triggered') + return Citizen.Await(p) +end + +RegisterNetEvent(clientToServerBackToClientName, function(name, ...) + local clientRebound = cbRebounds[name] + if clientRebound then + clientRebound(...) + end + local data = cbData[name] + if not data then return end + local func = data.cb + if not func then return end + data.p:resolve(func(...) or true) + cbData[name] = nil +end) +----------------------------- + +-- server to client rebound +RegisterNetEvent(serverToClientName, function(name, ...) + local data = Callback[name] + if not data then return end + local func = data.callback + if not func then return end + local cb = function(...) + TriggerServerEvent(serverToClientBackToServerName, name, ...) + end + func(cb, ...) +end) +----------------------------- + +exports('RegisterCallback', Callback.Register) +exports('RegisterRebound', Callback.RegisterRebound) +exports('TriggerCallback', Callback.Trigger) + diff --git a/modules/utility/shared/prints.lua b/modules/utility/shared/prints.lua new file mode 100644 index 0000000..a3198ac --- /dev/null +++ b/modules/utility/shared/prints.lua @@ -0,0 +1,24 @@ +Prints = Prints or {} + +local function printMessage(level, color, message) + if type(message) == 'table' then + message = json.encode(message) + end + print(color .. '[' .. level .. ']:', message) +end + +Prints.Info = function(message) + printMessage('INFO', '^5', message) +end + +Prints.Warn = function(message) + printMessage('WARN', '^3', message) +end + +Prints.Error = function(message) + printMessage('ERROR', '^1', message) +end + +Prints.Debug = function(message) + printMessage('DEBUG', '^2', message) +end \ No newline at end of file diff --git a/modules/utility/shared/tables.lua b/modules/utility/shared/tables.lua new file mode 100644 index 0000000..af69c64 --- /dev/null +++ b/modules/utility/shared/tables.lua @@ -0,0 +1,108 @@ +Table = {} + +Table.CheckPopulated = function(tbl) + if #tbl == 0 then + for _, _ in pairs(tbl) do + return true + end + return false + end + return true +end + +Table.DeepClone = function(tbl, out, omit) + if type(tbl) ~= "table" then return tbl end + local new = out or {} + omit = omit or {} + for key, data in pairs(tbl) do + if not omit[key] then + if type(data) == "table" then + new[key] = Table.DeepClone(data) + else + new[key] = data + end + end + end + return new +end + +Table.TableContains = function(tbl, search, nested) + for _, v in pairs(tbl) do + if nested and type(v) == "table" then + return Table.TableContains(v, search) + elseif v == search then + return true, v + end + end + return false +end + +Table.TableContainsKey = function(tbl, search) + for k, _ in pairs(tbl) do + if k == search then + return true, k + end + end + return false +end + +Table.GetClosest = function(coords, tbl) + local closestPoint = nil + local dist = math.huge + for k, v in pairs(tbl) do + local c = v.coords + local d = c and #(coords - c) + if d < dist then + dist = d + closestPoint = v + end + end + return closestPoint +end + +Table.FindFirstUnoccupiedSlot = function(tbl) + local occupiedSlots = {} + for _, v in pairs(tbl) do + occupiedSlots[v.slot] = true + end + for i = 1, BridgeServerConfig.MaxInventorySlots do + if not occupiedSlots[i] then + return i + end + end + return nil +end + +Table.Append = function(tbl1, tbl2) + for _, v in pairs(tbl2) do + table.insert(tbl1, v) + end + return tbl1 +end + +Table.Split = function(tbl, size) + local new1 = {} + local new2 = {} + size = size or math.floor(#tbl / 2) + + if size > #tbl then + assert(false, "Size is greater than the length of the table.") + end + for i = 1, size do + table.insert(new1, tbl[i]) + end + for i = size + 1, #tbl do + table.insert(new2, tbl[i]) + end + return new1, new2 +end + +Table.Shuffle = function(tbl) + for i = #tbl, 2, -1 do + local j = math.random(i) + tbl[i], tbl[j] = tbl[j], tbl[i] + end + return tbl +end + +return Table \ No newline at end of file diff --git a/modules/utility/shared/uniqueids.lua b/modules/utility/shared/uniqueids.lua new file mode 100644 index 0000000..f950b30 --- /dev/null +++ b/modules/utility/shared/uniqueids.lua @@ -0,0 +1,25 @@ +Utility = Utility or {} +-- for unique ids +Utility.CreateUniqueId = function(tbl, len, pattern) -- both optional + tbl = tbl or {} -- table to check uniqueness. Ids to check against must be the key to the tables value + len = len or 8 + + local id = "" + for i = 1, len do + local char = "" + if pattern then + char = pattern:sub(math.random(1, #pattern), math.random(1, #pattern)) + else + char = math.random(1, 2) == 1 and string.char(math.random(65, 90)) or math.random(0, 9) -- CAP letter and number + end + id = id .. char + end + if tbl[id] then + return Utility.CreateUniqueId(tbl, len, pattern) + end + return id +end + +Utility.RandomString = function() + return Utility.CreateUniqueId(nil, 14, nil) +end \ No newline at end of file diff --git a/modules/vehicleKey/MrNewbVehicleKeys/client.lua b/modules/vehicleKey/MrNewbVehicleKeys/client.lua new file mode 100644 index 0000000..75778f6 --- /dev/null +++ b/modules/vehicleKey/MrNewbVehicleKeys/client.lua @@ -0,0 +1,13 @@ +if GetResourceState('MrNewbVehicleKeys') ~= 'started' then return end +VehicleKey = {} + +VehicleKey.GiveKeys = function(vehicle, plate) + if not DoesEntityExist(vehicle) then return false end + return exports.MrNewbVehicleKeys:GiveKeys(vehicle) +end + +VehicleKey.RemoveKeys = function(vehicle, plate) + if not vehicle and not plate then return false end + if not DoesEntityExist(vehicle) then return exports.MrNewbVehicleKeys:RemoveKeysByPlate(plate) end + return exports.MrNewbVehicleKeys:RemoveKeys(vehicle) +end \ No newline at end of file diff --git a/modules/vehicleKey/Renewed-Vehiclekeys/client.lua b/modules/vehicleKey/Renewed-Vehiclekeys/client.lua new file mode 100644 index 0000000..6d502de --- /dev/null +++ b/modules/vehicleKey/Renewed-Vehiclekeys/client.lua @@ -0,0 +1,12 @@ +if GetResourceState('Renewed-Vehiclekeys') ~= 'started' then return end +VehicleKey = {} + +VehicleKey.GiveKeys = function(vehicle, plate) + if not DoesEntityExist(vehicle) then return false end + return exports['Renewed-Vehiclekeys']:addKey(plate) +end + +VehicleKey.RemoveKeys = function(vehicle, plate) + if not DoesEntityExist(vehicle) then return false end + return exports['Renewed-Vehiclekeys']:removeKey(plate) +end \ No newline at end of file diff --git a/modules/vehicleKey/cd_garage/client.lua b/modules/vehicleKey/cd_garage/client.lua new file mode 100644 index 0000000..310b9eb --- /dev/null +++ b/modules/vehicleKey/cd_garage/client.lua @@ -0,0 +1,10 @@ +if GetResourceState('cd_garage') ~= 'started' then return end +VehicleKey = {} + +VehicleKey.GiveKeys = function(vehicle, plate) + TriggerEvent('cd_garage:AddKeys', plate) +end + +VehicleKey.RemoveKeys = function(vehicle, plate) + +end \ No newline at end of file diff --git a/modules/vehicleKey/mk_vehiclekeys/client.lua b/modules/vehicleKey/mk_vehiclekeys/client.lua new file mode 100644 index 0000000..82d7f4c --- /dev/null +++ b/modules/vehicleKey/mk_vehiclekeys/client.lua @@ -0,0 +1,12 @@ +if GetResourceState('mk_vehiclekeys') ~= 'started' then return end +VehicleKey = {} + +VehicleKey.GiveKeys = function(vehicle, plate) + if not DoesEntityExist(vehicle) then return false end + return exports["mk_vehiclekeys"]:AddKey(vehicle) +end + +VehicleKey.RemoveKeys = function(vehicle, plate) + if not DoesEntityExist(vehicle) then return false end + return exports["mk_vehiclekeys"]:RemoveKey(vehicle) +end \ No newline at end of file diff --git a/modules/vehicleKey/okokGarage/client.lua b/modules/vehicleKey/okokGarage/client.lua new file mode 100644 index 0000000..88543e4 --- /dev/null +++ b/modules/vehicleKey/okokGarage/client.lua @@ -0,0 +1,10 @@ +if GetResourceState('okokGarage') ~= 'started' then return end +VehicleKey = {} + +VehicleKey.GiveKeys = function(vehicle, plate) + TriggerServerEvent('okokGarage:GiveKeys', plate) +end + +VehicleKey.RemoveKeys = function(vehicle, plate) + return true +end \ No newline at end of file diff --git a/modules/vehicleKey/qb-vehiclekeys/client.lua b/modules/vehicleKey/qb-vehiclekeys/client.lua new file mode 100644 index 0000000..226200e --- /dev/null +++ b/modules/vehicleKey/qb-vehiclekeys/client.lua @@ -0,0 +1,11 @@ +if GetResourceState('qb-vehiclekeys') ~= 'started' then return end +if GetResourceState('qbx_vehiclekeys') == 'started' then return end +VehicleKey = {} + +VehicleKey.GiveKeys = function(vehicle, plate) + TriggerServerEvent('qb-vehiclekeys:server:AcquireVehicleKeys', plate) +end + +VehicleKey.RemoveKeys = function(vehicle, plate) + return true +end \ No newline at end of file diff --git a/modules/vehicleKey/qbx_vehiclekeys/client.lua b/modules/vehicleKey/qbx_vehiclekeys/client.lua new file mode 100644 index 0000000..f46158c --- /dev/null +++ b/modules/vehicleKey/qbx_vehiclekeys/client.lua @@ -0,0 +1,10 @@ +if GetResourceState('qbx_vehiclekeys') ~= 'started' then return end +VehicleKey = {} + +VehicleKey.GiveKeys = function(vehicle, plate) + TriggerServerEvent('qb-vehiclekeys:server:AcquireVehicleKeys', plate) +end + +VehicleKey.RemoveKeys = function(vehicle, plate) + return true +end \ No newline at end of file diff --git a/modules/vehicleKey/qs-vehiclekeys/client.lua b/modules/vehicleKey/qs-vehiclekeys/client.lua new file mode 100644 index 0000000..aca4377 --- /dev/null +++ b/modules/vehicleKey/qs-vehiclekeys/client.lua @@ -0,0 +1,12 @@ +if GetResourceState('qs-vehiclekeys') ~= 'started' then return end +VehicleKey = {} + +VehicleKey.GiveKeys = function(vehicle, plate) + local model = GetDisplayNameFromVehicleModel(GetEntityModel(vehicle)) + local verifiedPlate = GetVehicleNumberPlateText(vehicle) + exports['qs-vehiclekeys']:GiveKeys(verifiedPlate, model, true) +end + +VehicleKey.RemoveKeys = function(vehicle, plate) + return true +end \ No newline at end of file diff --git a/modules/vehicleKey/t1ger_keys/client.lua b/modules/vehicleKey/t1ger_keys/client.lua new file mode 100644 index 0000000..112e14b --- /dev/null +++ b/modules/vehicleKey/t1ger_keys/client.lua @@ -0,0 +1,12 @@ +if GetResourceState('t1ger_keys') ~= 'started' then return end +VehicleKey = {} + +VehicleKey.GiveKeys = function(vehicle, plate) + if not DoesEntityExist(vehicle) then return false end + local vehicle_display_name = GetDisplayNameFromVehicleModel(GetEntityModel(vehicle)) + return exports['t1ger_keys']:GiveTemporaryKeys(plate, vehicle_display_name, 'some_keys') +end + +VehicleKey.RemoveKeys = function(vehicle, plate) + +end \ No newline at end of file diff --git a/modules/vehicleKey/wasabi_carlock/client.lua b/modules/vehicleKey/wasabi_carlock/client.lua new file mode 100644 index 0000000..d71e8a6 --- /dev/null +++ b/modules/vehicleKey/wasabi_carlock/client.lua @@ -0,0 +1,10 @@ +if GetResourceState('wasabi_carlock') ~= 'started' then return end +VehicleKey = {} + +VehicleKey.GiveKeys = function(vehicle, plate) + exports.wasabi_carlock:GiveKey(plate) +end + +VehicleKey.RemoveKeys = function(vehicle, plate) + exports.wasabi_carlock:RemoveKey(plate) +end \ No newline at end of file diff --git a/modules/weather/qb-weathersync/client.lua b/modules/weather/qb-weathersync/client.lua new file mode 100644 index 0000000..154a846 --- /dev/null +++ b/modules/weather/qb-weathersync/client.lua @@ -0,0 +1,10 @@ +if GetResourceState('qb-weathersync') ~= 'started' then return end +Weather = {} + +Weather.ToggleSync = function(toggle) + if toggle then + TriggerEvent("qb-weathersync:client:EnableSync") + else + TriggerEvent("qb-weathersync:client:DisableSync") + end +end \ No newline at end of file diff --git a/modules/weather/renewed-weathersync/client.lua b/modules/weather/renewed-weathersync/client.lua new file mode 100644 index 0000000..a8a1766 --- /dev/null +++ b/modules/weather/renewed-weathersync/client.lua @@ -0,0 +1,6 @@ +if GetResourceState('Renewed-Weathersync') ~= 'started' then return end +Weather = {} + +Weather.ToggleSync = function(toggle) + LocalPlayer.state.syncWeather = toggle +end \ No newline at end of file diff --git a/modules/weather/vSync/client.lua b/modules/weather/vSync/client.lua new file mode 100644 index 0000000..154a846 --- /dev/null +++ b/modules/weather/vSync/client.lua @@ -0,0 +1,10 @@ +if GetResourceState('qb-weathersync') ~= 'started' then return end +Weather = {} + +Weather.ToggleSync = function(toggle) + if toggle then + TriggerEvent("qb-weathersync:client:EnableSync") + else + TriggerEvent("qb-weathersync:client:DisableSync") + end +end \ No newline at end of file