mirror of
https://github.com/jimathy/jim_bridge.git
synced 2026-08-17 22:16:03 +01:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b07c089946 | ||
|
|
d603067c77 | ||
|
|
5a97b8f83a | ||
|
|
d0a09871c7 | ||
|
|
e87aa8d74d | ||
|
|
e204e6153d | ||
|
|
5c69f8dd28 | ||
|
|
f3fa309dbf | ||
|
|
9d74e7cb46 |
32
clientFrameworkCache.lua
Normal file
32
clientFrameworkCache.lua
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
if _G.__bridge_cache_loaded then return end
|
||||||
|
_G.__bridge_cache_loaded = true
|
||||||
|
|
||||||
|
_G.BridgeCache = {
|
||||||
|
hasCache = false,
|
||||||
|
data = nil,
|
||||||
|
queue = {},
|
||||||
|
}
|
||||||
|
|
||||||
|
RegisterNetEvent("jim_bridge:receiveCache", function(data)
|
||||||
|
if _G.BridgeCache.hasCache then return end
|
||||||
|
_G.BridgeCache.data = data
|
||||||
|
_G.BridgeCache.hasCache = true
|
||||||
|
|
||||||
|
for _, cb in ipairs(_G.BridgeCache.queue) do
|
||||||
|
cb(data)
|
||||||
|
end
|
||||||
|
_G.BridgeCache.queue = nil
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- Only send the request ONCE per client session
|
||||||
|
TriggerServerEvent("jim_bridge:requestCache")
|
||||||
|
|
||||||
|
-- Exported async function
|
||||||
|
function GetBridgeCache(callback)
|
||||||
|
if _G.BridgeCache.hasCache then
|
||||||
|
callback(_G.BridgeCache.data)
|
||||||
|
else
|
||||||
|
table.insert(_G.BridgeCache.queue, callback)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
exports("GetBridgeCache", GetBridgeCache)
|
||||||
@@ -35,9 +35,12 @@ local Exports = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
-- Prevent reloading if cache is already initialized
|
-- Prevent reloading if cache is already initialized
|
||||||
if _G.__jimBridgeDataCache then return end
|
local cache = {
|
||||||
_G.__jimBridgeDataCache = {}
|
Items = {},
|
||||||
local cache = _G.__jimBridgeDataCache
|
Vehicles = {},
|
||||||
|
Jobs = {},
|
||||||
|
Gangs = {},
|
||||||
|
}
|
||||||
|
|
||||||
-- Helper function to check if resource exists in server (instead of if it is already started)
|
-- Helper function to check if resource exists in server (instead of if it is already started)
|
||||||
local function checkExists(resourceName)
|
local function checkExists(resourceName)
|
||||||
@@ -62,7 +65,6 @@ if checkExists(Exports.ESXExport) then
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Initialize variables for caching
|
-- Initialize variables for caching
|
||||||
local Items, Vehicles, Jobs, Gangs, Core = {}, {}, {}, {}, nil
|
|
||||||
local itemResource, jobResource, vehResource = "N/A", "N/A", "N/A"
|
local itemResource, jobResource, vehResource = "N/A", "N/A", "N/A"
|
||||||
|
|
||||||
-- Print just to announce it knows the exports/scripts exist in the server
|
-- Print just to announce it knows the exports/scripts exist in the server
|
||||||
@@ -85,22 +87,15 @@ if checkExists(Exports.OXInv) then
|
|||||||
return exports[Exports.OXInv]:Items()
|
return exports[Exports.OXInv]:Items()
|
||||||
end)
|
end)
|
||||||
if success and result then
|
if success and result then
|
||||||
Items = result
|
cache.Items = result
|
||||||
end
|
|
||||||
|
|
||||||
if Items == nil or not next(Items) then
|
|
||||||
print("^1--------------------------------------------^7")
|
|
||||||
print("^1ERROR^7: ^1Can NOT find "..Exports.OXInv.." ^7Items ^1list^7, ^1possible error in that file^7?")
|
|
||||||
print("^1--------------------------------------------^7")
|
|
||||||
Items = {} -- Fallback to an empty table
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Get Weapon info and duplicate them if they are uppercase
|
-- Get Weapon info and duplicate them if they are uppercase
|
||||||
-- (duplicate incase anything checks for the uppercase version)
|
-- (duplicate incase anything checks for the uppercase version)
|
||||||
for k, v in pairs(Items) do
|
for k, v in pairs(cache.Items) do
|
||||||
if type(k) == "string" then
|
if type(k) == "string" then
|
||||||
if k:find("WEAPON") then
|
if k:find("WEAPON") then
|
||||||
Items[k:lower()] = Items[k]
|
cache.Items[k:lower()] = cache.Items[k]
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
print("^1ERROR^7: ^1Possible table inside a table, check your items.lua^7?")
|
print("^1ERROR^7: ^1Possible table inside a table, check your items.lua^7?")
|
||||||
@@ -109,27 +104,48 @@ if checkExists(Exports.OXInv) then
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
elseif checkExists(Exports.QBXExport) then
|
||||||
|
while GetResourceState(Exports.QBXExport) ~= "started" do Wait(100) end
|
||||||
|
itemResource = Exports.QBXExport
|
||||||
|
cache.Items = exports[Exports.QBExport]:GetCoreObject().Shared.Items
|
||||||
|
-- If this is nil, they need to update to qbx_core 1.23.0+
|
||||||
|
if not cache.Items then
|
||||||
|
-- if their inventory doesn't allow that (they refuse to update their butchered core replacement):
|
||||||
|
if GetResourceState(Exports.QSInv):find("start") then
|
||||||
|
itemResource = Exports.QSInv
|
||||||
|
cache.Items = exports[Exports.QSInv]:GetItemList()
|
||||||
|
|
||||||
|
elseif GetResourceState(Exports.OrigenInv):find("start") then
|
||||||
|
itemResource = Exports.OrigenInv
|
||||||
|
cache.Items = exports[Exports.OrigenInv]:Items()
|
||||||
|
|
||||||
|
elseif GetResourceState(Exports.CodeMInv):find("start") then
|
||||||
|
itemResource = Exports.CodeMInv
|
||||||
|
cache.Items = exports[Exports.CodeMInv]:GetItemList()
|
||||||
|
|
||||||
|
elseif GetResourceState(Exports.CoreInv):find("start") then
|
||||||
|
itemResource = Exports.CoreInv
|
||||||
|
cache.Items = exports[Exports.CoreInv]:getItemsList()
|
||||||
|
|
||||||
|
elseif GetResourceState(Exports.TgiannInv):find("start") then
|
||||||
|
itemResource = Exports.TgiannInv
|
||||||
|
cache.Items = exports[Exports.TgiannInv]:Items()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
elseif checkExists(Exports.QBExport) then
|
elseif checkExists(Exports.QBExport) then
|
||||||
while GetResourceState(Exports.QBExport) ~= "started" do Wait(100) end
|
while GetResourceState(Exports.QBExport) ~= "started" do Wait(100) end
|
||||||
itemResource = Exports.QBExport
|
itemResource = Exports.QBExport
|
||||||
Core = exports[Exports.QBExport]:GetCoreObject()
|
cache.Items = exports[Exports.QBExport]:GetCoreObject().Shared.Items
|
||||||
Items = Core.Shared.Items
|
|
||||||
|
|
||||||
if Items == nil or not next(Items) then
|
|
||||||
print("^1--------------------------------------------^7")
|
|
||||||
print("^1ERROR^7: ^1Can NOT find "..Exports.QBExport.." ^7Items ^1list^7, ^1possible error in that file^7?")
|
|
||||||
print("^1--------------------------------------------^7")
|
|
||||||
Items = {} -- Fallback to an empty table
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif checkExists(Exports.ESXExport) then
|
elseif checkExists(Exports.ESXExport) then
|
||||||
itemResource = Exports.ESXExport
|
itemResource = Exports.ESXExport
|
||||||
if GetResourceState(Exports.QSInv):find("start") then
|
if GetResourceState(Exports.QSInv):find("start") then
|
||||||
Items = exports[Exports.QSInv]:GetItemList()
|
cache.Items = exports[Exports.QSInv]:GetItemList()
|
||||||
else
|
else
|
||||||
Items = ESX.GetItems()
|
cache.Items = ESX.GetItems()
|
||||||
while not next(Items) do
|
while not next(cache.Items) do
|
||||||
Items = ESX.GetItems()
|
cache.Items = ESX.GetItems()
|
||||||
Wait(1000)
|
Wait(1000)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -137,37 +153,26 @@ elseif checkExists(Exports.ESXExport) then
|
|||||||
elseif checkExists(Exports.RSGExport) then
|
elseif checkExists(Exports.RSGExport) then
|
||||||
while GetResourceState(Exports.RSGExport) ~= "started" do Wait(100) end
|
while GetResourceState(Exports.RSGExport) ~= "started" do Wait(100) end
|
||||||
itemResource = Exports.RSGExport
|
itemResource = Exports.RSGExport
|
||||||
Core = exports[Exports.RSGExport]:GetCoreObject()
|
cache.Items = exports[Exports.RSGExport]:GetCoreObject().Shared.Items
|
||||||
Items = Core.Shared.Items
|
|
||||||
if Items == nil or not next(Items) then
|
|
||||||
print("^1--------------------------------------------^7")
|
|
||||||
print("^1ERROR^7: ^1Can NOT find "..Exports.RSGExport.." ^7Items ^1list^7, ^1possible error in that file^7?")
|
|
||||||
print("^1--------------------------------------------^7")
|
|
||||||
Items = {} -- Fallback to an empty table
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
---------------------
|
---------------------
|
||||||
--- Load Vehicles ---
|
--- Load Vehicles ---
|
||||||
---------------------
|
---------------------
|
||||||
-- Vehicle loading depending on framework
|
-- Vehicle loading depending on framework
|
||||||
if checkExists(Exports.QBXExport) or checkExists(Exports.QBExport) then
|
if checkExists(Exports.QBXExport) then
|
||||||
|
vehResource = Exports.QBXExport
|
||||||
|
cache.Vehicles = exports[Exports.QBExport]:GetCoreObject().Shared.Vehicles
|
||||||
|
|
||||||
|
elseif checkExists(Exports.QBExport)then
|
||||||
vehResource = Exports.QBExport
|
vehResource = Exports.QBExport
|
||||||
Core = Core or exports[Exports.QBExport]:GetCoreObject()
|
cache.Vehicles = exports[Exports.QBExport]:GetCoreObject().Shared.Vehicles
|
||||||
Vehicles = Core.Shared.Vehicles
|
|
||||||
if Vehicles == nil or not next(Vehicles) then
|
|
||||||
print("^1--------------------------------------------^7")
|
|
||||||
print("^1ERROR^7: ^1Can NOT find "..Exports.QBExport.." ^7Vehicles ^1list^7, ^1possible error in that file^7?")
|
|
||||||
print("^1--------------------------------------------^7")
|
|
||||||
Vehicles = {} -- Fallback to an empty table
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif checkExists(Exports.OXCoreExport) then
|
elseif checkExists(Exports.OXCoreExport) then
|
||||||
vehResource = Exports.OXCoreExport
|
vehResource = Exports.OXCoreExport
|
||||||
Vehicles = {}
|
cache.Vehicles = {}
|
||||||
for k, v in pairs(Ox.GetVehicleData()) do
|
for k, v in pairs(Ox.GetVehicleData()) do
|
||||||
Vehicles[k] = {
|
cache.Vehicles[k] = {
|
||||||
model = k, hash = GetHashKey(k),
|
model = k, hash = GetHashKey(k),
|
||||||
price = v.price,
|
price = v.price,
|
||||||
name = v.name,
|
name = v.name,
|
||||||
@@ -178,9 +183,8 @@ elseif checkExists(Exports.OXCoreExport) then
|
|||||||
elseif checkExists(Exports.ESXExport) then
|
elseif checkExists(Exports.ESXExport) then
|
||||||
vehResource = Exports.ESXExport
|
vehResource = Exports.ESXExport
|
||||||
while not MySQL do Wait(1000) end
|
while not MySQL do Wait(1000) end
|
||||||
Vehicles = {}
|
|
||||||
for _, v in pairs(MySQL.query.await('SELECT model, price, name FROM vehicles')) do
|
for _, v in pairs(MySQL.query.await('SELECT model, price, name FROM vehicles')) do
|
||||||
Vehicles[v.model] = {
|
cache.Vehicles[v.model] = {
|
||||||
model = v.model,
|
model = v.model,
|
||||||
hash = GetHashKey(v.model),
|
hash = GetHashKey(v.model),
|
||||||
price = v.price,
|
price = v.price,
|
||||||
@@ -190,14 +194,7 @@ elseif checkExists(Exports.ESXExport) then
|
|||||||
|
|
||||||
elseif checkExists(Exports.RSGExport) then
|
elseif checkExists(Exports.RSGExport) then
|
||||||
vehResource = Exports.RSGExport
|
vehResource = Exports.RSGExport
|
||||||
Core = Core or exports[Exports.RSGExport]:GetCoreObject()
|
cache.Vehicles = exports[Exports.RSGExport]:GetCoreObject().Shared.Vehicles
|
||||||
Vehicles = Core.Shared.Vehicles
|
|
||||||
if Vehicles == nil or not next(Vehicles) then
|
|
||||||
print("^1--------------------------------------------^7")
|
|
||||||
print("^1ERROR^7: ^1Can NOT find shared ^7Vehicles ^1table^7, ^1possible error in that file^7?")
|
|
||||||
print("^1--------------------------------------------^7")
|
|
||||||
Vehicles = {} -- Fallback to an empty table
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -207,18 +204,14 @@ end
|
|||||||
-- Jobs loading based on framework
|
-- Jobs loading based on framework
|
||||||
if checkExists(Exports.QBXExport) then
|
if checkExists(Exports.QBXExport) then
|
||||||
jobResource = Exports.QBXExport
|
jobResource = Exports.QBXExport
|
||||||
Core = Core or exports[Exports.QBXExport]:GetCoreObject()
|
cache.Jobs, cache.Gangs = exports[Exports.QBXExport]:GetJobs(), exports[Exports.QBXExport]:GetGangs()
|
||||||
Jobs, Gangs = exports[Exports.QBXExport]:GetJobs(), exports[Exports.QBXExport]:GetGangs()
|
|
||||||
if Jobs == nil or not next(Jobs) then
|
elseif checkExists(Exports.QBExport) then
|
||||||
print("^1--------------------------------------------^7")
|
jobResource = Exports.QBExport
|
||||||
print("^1ERROR^7: ^1Can NOT find shared ^7Jobs ^1table^7, ^1possible error in that file^7?")
|
cache.Jobs, cache.Gangs = exports[Exports.QBExport]:GetCoreObject().Shared.Jobs, exports[Exports.QBExport]:GetCoreObject().Shared.Gangs
|
||||||
print("^1--------------------------------------------^7")
|
|
||||||
Jobs = {} -- Fallback to an empty table
|
|
||||||
end
|
|
||||||
|
|
||||||
elseif checkExists(Exports.OXCoreExport) then
|
elseif checkExists(Exports.OXCoreExport) then
|
||||||
jobResource = Exports.OXCoreExport
|
jobResource = Exports.OXCoreExport
|
||||||
Jobs = {}
|
|
||||||
while not MySQL do Wait(1000) end
|
while not MySQL do Wait(1000) end
|
||||||
local tempJobs = MySQL.query.await('SELECT * FROM `ox_groups`')
|
local tempJobs = MySQL.query.await('SELECT * FROM `ox_groups`')
|
||||||
local tempGrades = MySQL.query.await('SELECT * FROM `ox_group_grades`')
|
local tempGrades = MySQL.query.await('SELECT * FROM `ox_group_grades`')
|
||||||
@@ -228,34 +221,29 @@ elseif checkExists(Exports.OXCoreExport) then
|
|||||||
gradeMap[grade.group][grade.grade] = { name = grade.label }
|
gradeMap[grade.group][grade.grade] = { name = grade.label }
|
||||||
end
|
end
|
||||||
for _, job in pairs(tempJobs) do
|
for _, job in pairs(tempJobs) do
|
||||||
Jobs[job.name] = {
|
cache.Jobs[job.name] = {
|
||||||
label = job.label,
|
label = job.label,
|
||||||
grades = gradeMap[job.name] or {}
|
grades = gradeMap[job.name] or {}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
Gangs = Jobs
|
cache.Gangs = cache.Jobs
|
||||||
|
|
||||||
elseif checkExists(Exports.QBExport) then
|
|
||||||
jobResource = Exports.QBExport
|
|
||||||
Core = Core or exports[Exports.QBExport]:GetCoreObject()
|
|
||||||
Jobs, Gangs = Core.Shared.Jobs, Core.Shared.Gangs
|
|
||||||
|
|
||||||
elseif checkExists(Exports.ESXExport) then
|
elseif checkExists(Exports.ESXExport) then
|
||||||
jobResource = Exports.ESXExport
|
jobResource = Exports.ESXExport
|
||||||
ESX = exports[Exports.ESXExport]:getSharedObject()
|
ESX = exports[Exports.ESXExport]:getSharedObject()
|
||||||
Jobs = ESX.GetJobs()
|
cache.Jobs = ESX.GetJobs()
|
||||||
while not next(Jobs) do
|
while not next(cache.Jobs) do
|
||||||
Wait(100)
|
Wait(100)
|
||||||
Jobs = ESX.GetJobs()
|
cache.Jobs = ESX.GetJobs()
|
||||||
end
|
end
|
||||||
for Role, Grades in pairs(Jobs) do
|
for Role, Grades in pairs(cache.Jobs) do
|
||||||
-- Check for if user has added grades
|
-- Check for if user has added grades
|
||||||
if Grades.grades == nil or not next(Grades.grades) then
|
if Grades.grades == nil or not next(Grades.grades) then
|
||||||
goto continue
|
goto continue
|
||||||
end
|
end
|
||||||
for grade, info in pairs(Grades.grades) do
|
for grade, info in pairs(Grades.grades) do
|
||||||
if info.label and info.label:find("[Bb]oss") then
|
if info.label and info.label:find("[Bb]oss") then
|
||||||
Jobs[Role].grades[grade].isBoss = true
|
cache.Jobs[Role].grades[grade].isBoss = true
|
||||||
goto continue
|
goto continue
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -268,64 +256,159 @@ elseif checkExists(Exports.ESXExport) then
|
|||||||
end
|
end
|
||||||
|
|
||||||
if highestGrade then
|
if highestGrade then
|
||||||
Jobs[Role].grades[tostring(highestGrade)].isBoss = true
|
cache.Jobs[Role].grades[tostring(highestGrade)].isBoss = true
|
||||||
end
|
end
|
||||||
::continue::
|
::continue::
|
||||||
end
|
end
|
||||||
Gangs = Jobs
|
cache.Gangs = cache.Jobs
|
||||||
|
|
||||||
elseif checkExists(Exports.RSGExport) then
|
elseif checkExists(Exports.RSGExport) then
|
||||||
jobResource = Exports.RSGExport
|
jobResource = Exports.RSGExport
|
||||||
Core = Core or exports[Exports.RSGExport]:GetCoreObject()
|
cache.Jobs, cache.Gangs = exports[Exports.RSGExport]:GetCoreObject().Shared.Jobs, exports[Exports.RSGExport]:GetCoreObject().Shared.Gangs
|
||||||
Jobs, Gangs = Core.Shared.Jobs, Core.Shared.Gangs
|
|
||||||
if Jobs == nil or not next(Jobs) then
|
|
||||||
print("^1--------------------------------------------^7")
|
|
||||||
print("^1ERROR^7: ^1Can NOT find shared ^7Jobs ^1table^7, ^1possible error in that file^7?")
|
|
||||||
print("^1--------------------------------------------^7")
|
|
||||||
Jobs = {} -- Fallback to an empty table
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Save to global cache
|
-- Fallback if nil or empty
|
||||||
cache.Items = Items
|
if cache.Items == nil or not next(cache.Items) then
|
||||||
cache.Vehicles = Vehicles
|
print("^1--------------------------------------------^7")
|
||||||
cache.Jobs = Jobs
|
print("^1ERROR^7: ^1Can NOT find "..itemResource.." ^7Items ^1list^7, ^1possible error in that file or is it empty^7?")
|
||||||
cache.Gangs = Gangs
|
print("^1--------------------------------------------^7")
|
||||||
|
cache.Items = {} -- Fallback to an empty table
|
||||||
|
end
|
||||||
|
if cache.Vehicles == nil or not next(cache.Vehicles) then
|
||||||
|
print("^1--------------------------------------------^7")
|
||||||
|
print("^1ERROR^7: ^1Can NOT find "..vehResource.." ^7Vehicles ^1list^7, ^1possible error in that file or is it empty^7?")
|
||||||
|
print("^1--------------------------------------------^7")
|
||||||
|
cache.Vehicles = {} -- Fallback to an empty table
|
||||||
|
end
|
||||||
|
if cache.Jobs == nil or not next(cache.Jobs) then
|
||||||
|
print("^1--------------------------------------------^7")
|
||||||
|
print("^1ERROR^7: ^1Can NOT find "..jobResource.." ^7job ^1list^7, ^1possible error in that file or is it empty^7?")
|
||||||
|
print("^1--------------------------------------------^7")
|
||||||
|
cache.Jobs = {} -- Fallback to an empty table
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Auto Detection of Inventory Weight -- **EXPERIMENTAL**
|
||||||
|
-- Forcefully load the the specified config file from inventory scripts
|
||||||
|
-- This allows to get information required for certain functions that need to detect how much space is left in a players inventory
|
||||||
|
-- This is born from too many tickets of me needing to explain that they need to change "InventoryWeight" to match their inv setting
|
||||||
|
local function getInventoryConfig(resource, data)
|
||||||
|
if data.convars then
|
||||||
|
return function(path)
|
||||||
|
local key = path[1]
|
||||||
|
local convar = key == "MaxWeight" and data.convars.weight or key == "MaxSlots" and data.convars.slots
|
||||||
|
return convar and GetConvarInt(convar.key, convar.default) or nil, "Unsupported convar path: " .. table.concat(path, ".")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local content = LoadResourceFile(resource, data.file)
|
||||||
|
if not content then return nil, "Failed to load file" end
|
||||||
|
|
||||||
|
local env = {
|
||||||
|
GetConvar = GetConvar, vector3 = vector3, Citizen = Citizen,
|
||||||
|
GetResourceState = GetResourceState, exports = exports,
|
||||||
|
DependencyCheck = DependencyCheck or function() return nil end,
|
||||||
|
}
|
||||||
|
|
||||||
|
local fn, err = load(content, '@'..data.file, 't', env)
|
||||||
|
if not fn then return nil, "Failed to compile config: " .. err end
|
||||||
|
if not pcall(fn) then return nil, "Error executing config file" end
|
||||||
|
|
||||||
|
local cfg = env.Config or env.config
|
||||||
|
if not cfg then return nil, "Config table not found" end
|
||||||
|
|
||||||
|
return function(path)
|
||||||
|
local ref = cfg
|
||||||
|
for _, k in ipairs(path) do
|
||||||
|
if type(ref) ~= "table" then return nil, "Path invalid at: " .. tostring(k) end
|
||||||
|
ref = ref[k]
|
||||||
|
end
|
||||||
|
return ref
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
-- Inventory table
|
||||||
|
local invWeightTable = {
|
||||||
|
[Exports.OXInv] = { convars = {
|
||||||
|
weight = { key = "inventory:weight", default = 30000 },
|
||||||
|
slots = { key = "inventory:slots", default = 40 }
|
||||||
|
}},
|
||||||
|
[Exports.QBInv] = { file = "config/config.lua", path = { "MaxWeight" }, slotPath = { "MaxSlots" } },
|
||||||
|
[Exports.JPRInv] = { file = "configs/main_config.lua", path = { "MaxInventoryWeight" }, slotPath = { "MaxInventorySlots" } },
|
||||||
|
[Exports.PSInv] = { file = "config.lua", path = { "MaxInventoryWeight" }, slotPath = { "MaxInventorySlots" } },
|
||||||
|
[Exports.QSInv] = { file = "config/config.lua", path = { "InventoryWeight", "weight" }, slotPath = { "InventoryWeight", "slots" } },
|
||||||
|
[Exports.TgiannInv] = { file = "configs/config.lua", path = { "slotsMaxWeights", "player", "maxWeight" }, slotPath = { "slotsMaxWeights", "player", "slots" } },
|
||||||
|
[Exports.CodeMInv] = { file = "config/config.lua", path = { "MaxWeight" }, slotPath = { "MaxSlots" } },
|
||||||
|
[Exports.RSGInv] = { file = "config/config.lua", path = { "MaxWeight" }, slotPath = { "MaxSlots" } },
|
||||||
|
--[Exports.OrigenInv] = { file = "config.lua", path = { "MaxWeight" } },
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Run config detection
|
||||||
|
local invResource = ""
|
||||||
|
for script, data in pairs(invWeightTable) do
|
||||||
|
if checkExists(script) then
|
||||||
|
if script == Exports.QBInv and GetResourceState(Exports.JPRInv):find("start") then return end
|
||||||
|
|
||||||
|
local lookup, err = getInventoryConfig(script, data)
|
||||||
|
if not lookup then
|
||||||
|
print(("^1ERROR^7: ^1Config loader failed from ^5%s^7: ^1%s^7"):format(script, err or "unknown"))
|
||||||
|
break
|
||||||
|
end
|
||||||
|
|
||||||
|
local function resolve(label, path)
|
||||||
|
local val, perr = lookup(path)
|
||||||
|
if val then
|
||||||
|
cache["Inventory"..label] = val
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local warnType = label == "Weight" and "^1ERROR" or "^3WARNING"
|
||||||
|
print(("%s^7: ^1Failed to get ^7Inventory%s ^1from ^5%s^7: ^1%s^7"):format(warnType, label, script, perr or "unknown"))
|
||||||
|
end
|
||||||
|
|
||||||
|
resolve("Weight", data.path or { "MaxWeight" })
|
||||||
|
resolve("Slots", data.slotPath or { "MaxSlots" })
|
||||||
|
|
||||||
|
invResource = script:gsub("-", "^7-^4"):gsub("_", "^7_^4")
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
CreateThread(function()
|
CreateThread(function()
|
||||||
local counts = {
|
local counts = {
|
||||||
Items = 0,
|
Items = 0, Vehicles = 0, Jobs = 0, Gangs = 0,
|
||||||
Vehicles = 0,
|
|
||||||
Jobs = 0,
|
|
||||||
Gangs = 0,
|
|
||||||
}
|
}
|
||||||
for k, v in pairs(cache) do
|
for k, v in pairs(cache) do
|
||||||
for count in pairs(v) do
|
if type(v) ~= "number" then for count in pairs(v) do counts[k] += 1 end end
|
||||||
counts[k] += 1
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
print("^6FrameworkCache^7: ^2Loaded ^5"..tostring(counts.Items).."^2 Items from ^7"..itemResource)
|
if cache.InventoryWeight then
|
||||||
print("^6FrameworkCache^7: ^2Loaded ^5"..tostring(counts.Vehicles).."^2 Vehicles from ^7"..vehResource)
|
print("^6FrameWorkCache^7: ^4"..invResource.."^2 InventoryWeight^7: ^3"..cache.InventoryWeight.."^7 (^3"..(cache.InventoryWeight / 1000).."kg^7)")
|
||||||
print("^6FrameworkCache^7: ^2Loaded ^5"..tostring(counts.Jobs).."^2 Jobs from ^7"..jobResource)
|
end
|
||||||
print("^6FrameworkCache^7: ^2Loaded ^5"..tostring(counts.Gangs).."^2 Gangs from ^7"..jobResource)
|
if cache.InventorySlots then
|
||||||
|
print("^6FrameWorkCache^7: ^4"..invResource.."^2 InventorySlots^7: ^3"..cache.InventorySlots.."^7")
|
||||||
|
end
|
||||||
|
print("^6FrameworkCache^7: ^4"..itemResource:gsub("-", "^7-^4"):gsub("_", "^7_^4").."^2 Loaded ^3"..tostring(counts.Items).."^2 Items^7")
|
||||||
|
print("^6FrameworkCache^7: ^4"..vehResource:gsub("-", "^7-^4"):gsub("_", "^7_^4").."^2 Loaded ^3"..tostring(counts.Vehicles).."^2 Vehicles^7")
|
||||||
|
print("^6FrameworkCache^7: ^4"..jobResource:gsub("-", "^7-^4"):gsub("_", "^7_^4").."^2 Loaded ^3"..tostring(counts.Jobs).."^2 Jobs^7")
|
||||||
|
print("^6FrameworkCache^7: ^4"..jobResource:gsub("-", "^7-^4"):gsub("_", "^7_^4").."^2 Loaded ^3"..tostring(counts.Gangs).."^2 Gangs^7")
|
||||||
end)
|
end)
|
||||||
|
|
||||||
RegisterNetEvent("jim_bridge:requestCache", function()
|
RegisterNetEvent("jim_bridge:requestCache", function()
|
||||||
local src = source
|
local src = source
|
||||||
TriggerClientEvent("jim_bridge:receiveCache", src, _G.__jimBridgeDataCache)
|
TriggerClientEvent("jim_bridge:receiveCache", src, cache)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
exports("GetSharedData", function()
|
exports("GetSharedData", function()
|
||||||
-- Wait for data to be ready before returning it
|
-- Wait for data to be ready before returning it
|
||||||
local timeout = GetGameTimer() + 5000
|
local timeout = GetGameTimer() + 5000
|
||||||
while (
|
while (
|
||||||
not _G.__jimBridgeDataCache or
|
not cache or
|
||||||
(not _G.__jimBridgeDataCache.Items or next(_G.__jimBridgeDataCache.Items) == nil) or
|
(not cache.Items or next(cache.Items) == nil) or
|
||||||
(not _G.__jimBridgeDataCache.Vehicles or next(_G.__jimBridgeDataCache.Vehicles) == nil) or
|
(not cache.Vehicles or next(cache.Vehicles) == nil) or
|
||||||
(not _G.__jimBridgeDataCache.Jobs or next(_G.__jimBridgeDataCache.Jobs) == nil)
|
(not cache.Jobs or next(cache.Jobs) == nil)
|
||||||
) and GetGameTimer() < timeout do
|
) and GetGameTimer() < timeout do
|
||||||
Wait(50)
|
Wait(50)
|
||||||
end
|
end
|
||||||
return _G.__jimBridgeDataCache
|
return cache
|
||||||
end)
|
end)
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
name "Jim_Bridge"
|
name "Jim_Bridge"
|
||||||
author "Jimathy"
|
author "Jimathy"
|
||||||
version "2.0.18"
|
version "2.0.19"
|
||||||
description "Framework Bridge By Jimathy"
|
description "Framework Bridge By Jimathy"
|
||||||
fx_version "cerulean"
|
fx_version "cerulean"
|
||||||
rdr3_warning 'I acknowledge that this is a prerelease build of RedM, and I am aware my resources *will* become incompatible once RedM ships.'
|
rdr3_warning 'I acknowledge that this is a prerelease build of RedM, and I am aware my resources *will* become incompatible once RedM ships.'
|
||||||
@@ -18,9 +18,10 @@ files {
|
|||||||
-- Version checker
|
-- Version checker
|
||||||
server_scripts {
|
server_scripts {
|
||||||
'frameworkCache.lua',
|
'frameworkCache.lua',
|
||||||
'_versioncheck.lua'
|
'_versioncheck.lua',
|
||||||
}
|
}
|
||||||
|
|
||||||
client_scripts {
|
client_scripts {
|
||||||
'ui_modules/*.lua'
|
'clientFrameworkCache.lua',
|
||||||
|
'ui_modules/*.lua',
|
||||||
}
|
}
|
||||||
@@ -197,22 +197,23 @@ function waitForSharedLoad()
|
|||||||
local timeout = 100000 -- 10 seconds in milliseconds
|
local timeout = 100000 -- 10 seconds in milliseconds
|
||||||
local startTime = GetGameTimer()
|
local startTime = GetGameTimer()
|
||||||
local loaded = true
|
local loaded = true
|
||||||
--Wait(1000)
|
|
||||||
local count = {}
|
|
||||||
local loop = 0
|
local loop = 0
|
||||||
while ((not Jobs or not next(Jobs)) and (not Items or not next(Items)) and (not Vehicles or not next(Vehicles))) and (GetGameTimer() - startTime) < timeout do
|
while ((not Jobs or not next(Jobs)) or
|
||||||
if not messageShown then
|
(not Items or not next(Items)) or
|
||||||
|
(not Vehicles or not next(Vehicles))
|
||||||
|
) and ((GetGameTimer() - startTime) < timeout) do
|
||||||
|
if loop >= 3 and not messageShown then
|
||||||
if (not Jobs or not next(Jobs)) then
|
if (not Jobs or not next(Jobs)) then
|
||||||
debugPrint("^4Debug^7: ^2Waiting for Jobs to be loaded")
|
print("^4Debug^7: ^2Waiting for ^7Jobs^2 to be loaded")
|
||||||
end
|
end
|
||||||
if (not Items or not next(Items)) then
|
if (not Items or not next(Items)) then
|
||||||
debugPrint("^4Debug^7: ^2Waiting for Items to be loaded")
|
print("^4Debug^7: ^2Waiting for ^7Items^2 to be loaded")
|
||||||
end
|
end
|
||||||
if (not Vehicles or not next(Vehicles)) then
|
if (not Vehicles or not next(Vehicles)) then
|
||||||
debugPrint("^4Debug^7: ^2Waiting for Vehicles to be loaded")
|
print("^4Debug^7: ^2Waiting for ^7Vehicles^2 to be loaded")
|
||||||
end
|
end
|
||||||
|
messageShown = true
|
||||||
end
|
end
|
||||||
messageShown = true
|
|
||||||
--print((GetGameTimer() - startTime) < timeout)
|
--print((GetGameTimer() - startTime) < timeout)
|
||||||
Wait(1000)
|
Wait(1000)
|
||||||
if Jobs and Items and Vehicles then
|
if Jobs and Items and Vehicles then
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
Items, Vehicles, Jobs, Gangs, Core = {}, nil, nil, nil, nil
|
Items, Vehicles, Jobs, Gangs = nil, nil, nil, nil
|
||||||
|
|
||||||
-- Shared Exports Initialization
|
-- Shared Exports Initialization
|
||||||
Exports.PSInv = isStarted("lj-inventory") and "lj-inventory" or Exports.PSInv
|
Exports.PSInv = isStarted("lj-inventory") and "lj-inventory" or Exports.PSInv
|
||||||
@@ -33,80 +33,72 @@ end
|
|||||||
|
|
||||||
|
|
||||||
if IsDuplicityVersion() then
|
if IsDuplicityVersion() then
|
||||||
CreateThread(function()
|
local cache = nil
|
||||||
local cache = nil
|
local timeout = GetGameTimer() + 5000 -- 5 seconds max wait
|
||||||
local timeout = GetGameTimer() + 5000 -- 5 seconds max wait
|
|
||||||
|
|
||||||
-- Wait until jim_bridge is started and export is available
|
-- Wait until jim_bridge is started and export is available
|
||||||
while not cache and GetGameTimer() < timeout do
|
while not cache and GetGameTimer() < timeout do
|
||||||
if GetResourceState("jim_bridge"):find("start") then
|
if GetResourceState("jim_bridge"):find("start") then
|
||||||
local success, result = pcall(function()
|
local success, result = pcall(function()
|
||||||
return exports["jim_bridge"]:GetSharedData()
|
return exports["jim_bridge"]:GetSharedData()
|
||||||
end)
|
end)
|
||||||
if success and result then
|
if success and result then
|
||||||
cache = result
|
cache = result
|
||||||
--print(json.encode(cache, {indent = true}))
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
Wait(100)
|
|
||||||
end
|
end
|
||||||
|
Wait(100)
|
||||||
|
end
|
||||||
|
|
||||||
if not cache then
|
if not cache then
|
||||||
print("^1ERROR^7: ^2jim_bridge export not available after timeout^7.")
|
print("^1ERROR^7: ^2jim_bridge export not available after timeout^7.")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
Items = cache.Items
|
Items = cache.Items
|
||||||
Vehicles = cache.Vehicles
|
Vehicles = cache.Vehicles
|
||||||
Jobs = cache.Jobs
|
Jobs = cache.Jobs
|
||||||
Gangs = cache.Gangs
|
Gangs = cache.Gangs
|
||||||
|
InventoryWeight = cache.InventoryWeight or InventoryWeight
|
||||||
|
InventorySlots = cache.InventorySlots or 40
|
||||||
|
|
||||||
debugPrint("^6Bridge^7: ^2Shared cache successfully loaded from export^7.")
|
debugPrint("^6Bridge^7: ^2Shared cache successfully loaded from export^7.")
|
||||||
end)
|
--print(countTable(Items), countTable(Vehicles), countTable(Jobs))
|
||||||
else
|
else
|
||||||
local hasCache = false
|
-- Shared bridge cache - prevent duplicate listeners
|
||||||
-- 🔹 Client Side: Request from server
|
exports["jim_bridge"]:GetBridgeCache(function(cache)
|
||||||
_G.__jimBridgeDataCache = {}
|
|
||||||
|
|
||||||
RegisterNetEvent("jim_bridge:receiveCache", function(data)
|
|
||||||
if not hasCache then
|
|
||||||
_G.__jimBridgeDataCache = data
|
|
||||||
hasCache = true
|
|
||||||
else
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end)
|
|
||||||
|
|
||||||
TriggerServerEvent("jim_bridge:requestCache")
|
|
||||||
|
|
||||||
CreateThread(function()
|
|
||||||
while not _G.__jimBridgeDataCache or not next(_G.__jimBridgeDataCache) do Wait(50) end
|
|
||||||
local cache = _G.__jimBridgeDataCache
|
|
||||||
Items = cache.Items or {}
|
Items = cache.Items or {}
|
||||||
Vehicles = cache.Vehicles or {}
|
Vehicles = cache.Vehicles or {}
|
||||||
Jobs = cache.Jobs or {}
|
Jobs = cache.Jobs or {}
|
||||||
Gangs = cache.Gangs or {}
|
Gangs = cache.Gangs or {}
|
||||||
|
InventoryWeight = cache.InventoryWeight or InventoryWeight
|
||||||
|
InventorySlots = cache.InventorySlots or 50
|
||||||
|
|
||||||
if isStarted(ESXExport) then
|
CreateThread(function()
|
||||||
for _, v in pairs(Vehicles) do
|
if isStarted(ESXExport) then
|
||||||
Vehicles[v.model] = {
|
for _, v in pairs(Vehicles) do
|
||||||
model = v.model,
|
Vehicles[v.model] = {
|
||||||
hash = v.hash,
|
model = v.model,
|
||||||
price = v.price,
|
hash = v.hash,
|
||||||
name = v.name,
|
price = v.price,
|
||||||
brand = GetMakeNameFromVehicleModel(v.model):lower():gsub("^%l", string.upper)
|
name = v.name,
|
||||||
}
|
brand = GetMakeNameFromVehicleModel(v.model):lower():gsub("^%l", string.upper)
|
||||||
end
|
}
|
||||||
end
|
|
||||||
if isStarted(OXInv) then
|
|
||||||
for k, v in pairsByKeys(Items) do
|
|
||||||
local tempInfo = exports[OXInv]:Items(k)
|
|
||||||
if tempInfo and tempInfo.client then
|
|
||||||
Items[k].image = (tempInfo.client and tempInfo.client.image) and tempInfo.client.image:gsub("nui://"..OXInv.."/web/images/", "") or k..".png"
|
|
||||||
Items[k].hunger = tempInfo.client and tempInfo.client.hunger
|
|
||||||
Items[k].thirst = tempInfo.client and tempInfo.client.thirst
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
if isStarted(OXInv) then
|
||||||
|
for k, v in pairs(Items) do
|
||||||
|
local tempInfo = exports[OXInv]:Items(k)
|
||||||
|
Items[k].image = k..".png" -- Set default image
|
||||||
|
if tempInfo and tempInfo.client then -- if client info, check for hard set image
|
||||||
|
Items[k].image = (tempInfo.client.image) and tempInfo.client.image:gsub("nui://"..OXInv.."/web/images/", "") or Items[k].image
|
||||||
|
Items[k].hunger = tempInfo.client.hunger
|
||||||
|
Items[k].thirst = tempInfo.client.thirst
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
debugPrint("^6Bridge^7: ^2Shared cache successfully loaded from export^7.")
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -516,17 +516,19 @@ end
|
|||||||
--- ```lua
|
--- ```lua
|
||||||
--- TriggerServerEvent("script:server:setMetaData", { item = "drill", slot = 5, metadata = { durability = 80 } })
|
--- TriggerServerEvent("script:server:setMetaData", { item = "drill", slot = 5, metadata = { durability = 80 } })
|
||||||
--- ```
|
--- ```
|
||||||
RegisterNetEvent(getScript()..":server:setMetaData", function(data)
|
RegisterNetEvent(getScript()..":server:setMetaData", function(data, src)
|
||||||
local src = source
|
local src = src or source
|
||||||
if isStarted(QBInv) or isStarted(PSInv) or isStarted(RSGInv) or isStarted(JPRInv) then
|
if isStarted(QBInv) or isStarted(PSInv) or isStarted(RSGInv) or isStarted(JPRInv) then
|
||||||
debugPrint(src, data.item, 1, data.slot)
|
--debugPrint(src, data.item, 1, data.slot)
|
||||||
local Player = Core.Functions.GetPlayer(src)
|
local Player = Core.Functions.GetPlayer(src)
|
||||||
Player.PlayerData.items[data.slot].info = data.metadata
|
Player.PlayerData.items[data.slot].info = data.metadata
|
||||||
Player.PlayerData.items[data.slot].description = "HP : "..data.metadata.durability
|
if data.metadata.durability then
|
||||||
|
Player.PlayerData.items[data.slot].description = "HP : "..data.metadata.durability
|
||||||
|
end
|
||||||
Player.Functions.SetInventory(Player.PlayerData.items)
|
Player.Functions.SetInventory(Player.PlayerData.items)
|
||||||
|
|
||||||
elseif isStarted(OXInv) then
|
elseif isStarted(OXInv) then
|
||||||
exports[OXInv]:SetDurability(src, data.slot, data.metadata.durability)
|
exports[OXInv]:SetMetadata(src, data.slot, data.metadata)
|
||||||
|
|
||||||
elseif isStarted(QSInv) then
|
elseif isStarted(QSInv) then
|
||||||
exports[QSInv]:SetItemMetadata(src, data.slot, data.metadata)
|
exports[QSInv]:SetItemMetadata(src, data.slot, data.metadata)
|
||||||
@@ -868,6 +870,14 @@ function getCurrentInvWeight()
|
|||||||
return weight
|
return weight
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function hasFreeInventorySlots(slots, src)
|
||||||
|
local inv = getPlayerInv(src)
|
||||||
|
if (countTable(inv) + slots) <= InventorySlots then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
-------------------------------------------------------------
|
-------------------------------------------------------------
|
||||||
-- Check Item Existance - return boolean(true,false)
|
-- Check Item Existance - return boolean(true,false)
|
||||||
-------------------------------------------------------------
|
-------------------------------------------------------------
|
||||||
|
|||||||
@@ -225,7 +225,7 @@ if isStarted(PSInv) then
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
if versionCompare(GetResourceMetadata("ps-inventory", "version", 0), "1.0.6") then
|
if versionCompare(GetResourceMetadata(PSInv, "version", 0), "1.0.6") then
|
||||||
print("^6Bridge^7: ^4"..PSInv.."^2 Version above ^31.0.6^7, ^2forcing ^1QBInvNew ^2to ^1true^7")
|
print("^6Bridge^7: ^4"..PSInv.."^2 Version above ^31.0.6^7, ^2forcing ^1QBInvNew ^2to ^1true^7")
|
||||||
QBInvNew = true
|
QBInvNew = true
|
||||||
else
|
else
|
||||||
@@ -233,4 +233,4 @@ if isStarted(PSInv) then
|
|||||||
QBInvNew = false
|
QBInvNew = false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
19
version.txt
19
version.txt
@@ -1,17 +1,8 @@
|
|||||||
2.0.18
|
2.0.19
|
||||||
|
|
||||||
- Fix ox_inv client item caching (images)
|
- SetMetadata function now handles full metadata, not just durability
|
||||||
- Add better checks if errors in ox_inv items and add more prominent error messages all around
|
- Completely rework framework caching, it was lagging behind and breaking
|
||||||
- Tidy up several debugPrints
|
- Add new hasFreeInvnentorySlots() function
|
||||||
- Move AuthEvents to new file
|
- Add inv config file grabber, checks inventory configs for inventory weight/slots
|
||||||
- Fix clearStash error with PSInv and JPRInv
|
|
||||||
- Add extra trigger event for PSInv when opening stash (hopefully fix missing items for some)
|
|
||||||
- Fix onPlayerUnloaded() not triggering
|
|
||||||
- Add support for esx_society in openBossMenu()
|
|
||||||
- Added support for okokbilling to billPlayer()
|
|
||||||
- Rework progressBar and ui_modules folder
|
|
||||||
- Rework isAnimal.lua to be more automated and smarter
|
|
||||||
- Rework/Fix auto detection of QBInvNew
|
|
||||||
- Add new functions to get players current Inventory Weight
|
|
||||||
|
|
||||||
https://github.com/jimathy/jim_bridge
|
https://github.com/jimathy/jim_bridge
|
||||||
Reference in New Issue
Block a user