Adjust frameworkCache.lua to be table based

Reworked `frameworkCache.lua` to the new layout

Fix possibility of invisible props/ peds/vehicles on spawn

Start adding very basic and unfinished support for RedM VorpCore
This commit is contained in:
Jim Shield
2025-08-26 13:24:36 +01:00
parent a851f8823c
commit eafa881cf8
10 changed files with 331 additions and 220 deletions

View File

@@ -31,17 +31,18 @@ local Exports = {
-- REDM -- REDM
RSGExport = "rsg-core", RSGExport = "rsg-core",
RSGInv = "rsg-inventory" RSGInv = "rsg-inventory",
VorpExport = "vorp_core",
VorpInv = "vorp_inventory",
VorpMenu = "vorp_menu",
} }
-- Prevent reloading if cache is already initialized -- Prevent reloading if cache is already initialized
local cache = { local cache = { Items = {}, Vehicles = {}, Jobs = {}, Gangs = {}, }
Items = {},
Vehicles = {},
Jobs = {},
Gangs = {},
}
local cacheReady = false local cacheReady = false
-- Timer info, for debugging more then anything
local timers = {} local timers = {}
local function startTimer(label) local function startTimer(label)
timers[label] = GetGameTimer() timers[label] = GetGameTimer()
@@ -52,26 +53,57 @@ local function endTimer(label)
timers[label] = "("..(timers[label] / 1000).."s)" timers[label] = "("..(timers[label] / 1000).."s)"
end end
startTimer("Cache") startTimer("Items") startTimer("Vehicles") startTimer("Jobs") startTimer("InvWeight") startTimer("InvSlots") startTimer("Cache") startTimer("Items") startTimer("Vehicles") startTimer("Jobs") startTimer("InvWeight") startTimer("InvSlots")
-- Helper function to check if resource exists in server (instead of if it is already started)
-- Helper functions --
local function checkExists(resourceName) local function checkExists(resourceName)
return GetResourceState(resourceName):find("start") or GetResourceState(resourceName):find("stopped") local state = GetResourceState(resourceName)
return state and (state:find("start") or state:find("stopped"))
end end
-- Ensure oxmysql resource is loaded local function waitStarted(resourceName)
if checkExists(Exports.OXCoreExport) or checkExists(Exports.ESXExport) then while GetResourceState(resourceName) ~= "started" do Wait(100) end
end
local function waitStartedOrStopped(resourceName)
local state = GetResourceState(resourceName)
while state ~= "started" and state ~= "stopped" do
Wait(100)
state = GetResourceState(resourceName)
end
end
local function dupLowercaseWeapons(items)
for k, v in pairs(items or {}) do
if type(k) == "string" then
if k:find("WEAPON") then
items[k:lower()] = v
end
else
print("^1ERROR^7: ^1Possible table inside a table, check your items.lua^7?")
print("^1Possible Issue found^7:")
print(json.encode(items[k], { indent = true }))
end
end
end
-- Forceload libs --
-- Ensure oxmysql resource is loaded for jim_bridge internally
-- For some core's it needs to get data from the database
if checkExists(Exports.OXCoreExport) or checkExists(Exports.ESXExport) or checkExists(Exports.VorpExport) then
local fileLoader = assert(load(LoadResourceFile("oxmysql", ('lib/MySQL.lua')), ('@@oxmysql/lib/MySQL.lua'))) local fileLoader = assert(load(LoadResourceFile("oxmysql", ('lib/MySQL.lua')), ('@@oxmysql/lib/MySQL.lua')))
fileLoader() fileLoader()
end end
if checkExists(Exports.OXCoreExport) then if checkExists(Exports.OXCoreExport) then
-- Detected OX_Core in server, wait for it to be started if needed -- Detected OX_Core in server, wait for it to be started if needed
while GetResourceState(Exports.OXCoreExport) ~= "started" do Wait(100) end waitStartedOrStopped(Exports.OXCoreExport)
local fileLoader = assert(load(LoadResourceFile(Exports.OXCoreExport, ('lib/init.lua')), ('@@'..Exports.OXCoreExport..'/lib/init.lua'))) local fileLoader = assert(load(LoadResourceFile(Exports.OXCoreExport, ('lib/init.lua')), ('@@'..Exports.OXCoreExport..'/lib/init.lua')))
fileLoader() fileLoader()
end end
if checkExists(Exports.ESXExport) then if checkExists(Exports.ESXExport) then
-- Detected ESX in server, wait for it to be started if needed -- Detected ESX in server, wait for it to be started if needed
while GetResourceState(Exports.ESXExport) ~= "started" do Wait(100) end waitStarted(Exports.ESXExport)
local fileLoader = assert(load(LoadResourceFile(Exports.ESXExport, ('/imports.lua')), ('@@'..Exports.ESXExport..'/imports.lua'))) local fileLoader = assert(load(LoadResourceFile(Exports.ESXExport, ('/imports.lua')), ('@@'..Exports.ESXExport..'/imports.lua')))
fileLoader() fileLoader()
end end
@@ -89,225 +121,274 @@ end
--------------------- ---------------------
---- Load Items ----- ---- Load Items -----
--------------------- ---------------------
-- Items initialization based on detected inventory system
if checkExists(Exports.OXInv) then
-- Wait for OX Inventory to start if it's not already started
while GetResourceState(Exports.OXInv) ~= "started" do Wait(100) end
itemResource = Exports.OXInv
local success, result = pcall(function() local itemFunc = {
return exports[Exports.OXInv]:Items() { script = Exports.OXInv,
end) cacheItem = function()
if success and result then local success, result = pcall(function()
cache.Items = result return exports[Exports.OXInv]:Items()
end end)
if success and result then
-- Get Weapon info and duplicate them if they are uppercase cache.Items = result
-- (duplicate incase anything checks for the uppercase version)
for k, v in pairs(cache.Items) do
if type(k) == "string" then
if k:find("WEAPON") then
cache.Items[k:lower()] = cache.Items[k]
end end
else end,
print("^1ERROR^7: ^1Possible table inside a table, check your items.lua^7?") },
print("^1Possible Issue found^7:") { script = Exports.TgiannInv,
print(json.encode(cache.Items[k], {indent = true})) cacheItem = function()
end local success, result = pcall(function()
end return exports[Exports.TgiannInv]:Items()
end)
elseif checkExists(Exports.TgiannInv) then if success and result then
-- Wait for OX Inventory to start if it's not already started cache.Items = result
while GetResourceState(Exports.TgiannInv) ~= "started" do Wait(100) end
itemResource = Exports.TgiannInv
local success, result = pcall(function()
return exports[Exports.TgiannInv]:Items()
end)
if success and result then
cache.Items = result
end
-- Get Weapon info and duplicate them if they are uppercase
-- (duplicate incase anything checks for the uppercase version)
for k, v in pairs(cache.Items) do
if type(k) == "string" then
if k:find("WEAPON") then
cache.Items[k:lower()] = cache.Items[k]
end end
else end,
print("^1ERROR^7: ^1Possible table inside a table, check your items.lua^7?") },
print("^1Possible Issue found^7:") { script = Exports.QBXExport,
print(json.encode(cache.Items[k], {indent = true})) cacheItem = function()
end 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
end,
},
{ script = Exports.QBExport,
cacheItem = function()
cache.Items = exports[Exports.QBExport]:GetCoreObject().Shared.Items
end,
},
{ script = Exports.ESXExport,
cacheItem = function()
if GetResourceState(Exports.QSInv):find("start") then
cache.Items = exports[Exports.QSInv]:GetItemList()
else
cache.Items = ESX.GetItems()
while not next(cache.Items) do
cache.Items = ESX.GetItems()
Wait(1000)
end
end
end,
},
{ script = Exports.RSGExport,
cacheItem = function()
cache.Items = exports[Exports.RSGExport]:GetCoreObject().Shared.Items
end,
},
{ script = Exports.VorpInv,
cacheItem = function()
local dbItems = MySQL.query.await('SELECT * FROM `items`')
local tempItems = {}
for i = 1, #dbItems do
local v = dbItems[i]
tempItems[v.item] = {
name = v.item,
label = v.label,
weight = v.weight,
info = v.metadata,
usable = v.usable,
type = v.type,
description = v.desc,
}
end
cache.Items = tempItems
end,
},
}
for i = 1, #itemFunc do
local data = itemFunc[i]
if checkExists(data.script) then
waitStarted(data.script) -- Wait for detected script to start fully
data.cacheItem() -- run tablized function for core/inv
dupLowercaseWeapons(cache.Items) -- make usable weapon item names for jim_bridge
itemResource = data.script -- Grab script name to announce later
endTimer("Items") -- end timer
break -- break loop so it doesn't keep checking
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
while GetResourceState(Exports.QBExport) ~= "started" do Wait(100) end
itemResource = Exports.QBExport
cache.Items = exports[Exports.QBExport]:GetCoreObject().Shared.Items
elseif checkExists(Exports.ESXExport) then
itemResource = Exports.ESXExport
if GetResourceState(Exports.QSInv):find("start") then
cache.Items = exports[Exports.QSInv]:GetItemList()
else
cache.Items = ESX.GetItems()
while not next(cache.Items) do
cache.Items = ESX.GetItems()
Wait(1000)
end
end
elseif checkExists(Exports.RSGExport) then
while GetResourceState(Exports.RSGExport) ~= "started" do Wait(100) end
itemResource = Exports.RSGExport
cache.Items = exports[Exports.RSGExport]:GetCoreObject().Shared.Items
end end
endTimer("Items")
--------------------- ---------------------
--- Load Vehicles --- --- Load Vehicles ---
--------------------- ---------------------
-- Vehicle loading depending on framework ---
if checkExists(Exports.QBXExport) then local vehicleFunc = {
vehResource = Exports.QBXExport
cache.Vehicles = exports[Exports.QBExport]:GetCoreObject().Shared.Vehicles
elseif checkExists(Exports.QBExport)then { script = Exports.QBXExport,
vehResource = Exports.QBExport cacheVehicle = function()
cache.Vehicles = exports[Exports.QBExport]:GetCoreObject().Shared.Vehicles cache.Vehicles = exports[Exports.QBExport]:GetCoreObject().Shared.Vehicles
end,
},
{ script = Exports.QBExport,
cacheVehicle = function()
cache.Vehicles = exports[Exports.QBExport]:GetCoreObject().Shared.Vehicles
end,
},
{ script = Exports.OXCoreExport,
cacheVehicle = function()
cache.Vehicles = {}
for k, v in pairs(Ox.GetVehicleData()) do
cache.Vehicles[k] = {
model = k, hash = joaat(k),
price = v.price,
name = v.name,
brand = v.make
}
end
end,
},
{ script = Exports.ESXExport,
cacheVehicle = function()
while not MySQL do Wait(100) end
for _, v in pairs(MySQL.query.await('SELECT model, price, name FROM vehicles')) do
cache.Vehicles[v.model] = {
model = v.model,
hash = joaat(v.model),
price = v.price,
name = v.name,
}
end
end,
},
{ script = Exports.RSGExport,
cacheVehicle = function()
cache.Vehicles = exports[Exports.RSGExport]:GetCoreObject().Shared.Vehicles
end,
},
{ script = Exports.VorpExport,
cacheVehicle = function()
cache.Vehicles = { ["unkown"] = {} }
end,
},
}
elseif checkExists(Exports.OXCoreExport) then for i = 1, #vehicleFunc do
vehResource = Exports.OXCoreExport local data = vehicleFunc[i]
cache.Vehicles = {} if checkExists(data.script) then
for k, v in pairs(Ox.GetVehicleData()) do waitStarted(data.script) -- Wait for detected script to start fully
cache.Vehicles[k] = { data.cacheVehicle() -- run tablized function for core
model = k, hash = joaat(k), vehResource = data.script -- Grab script name to announce later
price = v.price, endTimer("Vehicles") -- end timer
name = v.name, break -- break loop so it doesn't keep checking
brand = v.make
}
end end
elseif checkExists(Exports.ESXExport) then
vehResource = Exports.ESXExport
while not MySQL do Wait(1000) end
for _, v in pairs(MySQL.query.await('SELECT model, price, name FROM vehicles')) do
cache.Vehicles[v.model] = {
model = v.model,
hash = joaat(v.model),
price = v.price,
name = v.name,
}
end
elseif checkExists(Exports.RSGExport) then
vehResource = Exports.RSGExport
cache.Vehicles = exports[Exports.RSGExport]:GetCoreObject().Shared.Vehicles
end end
endTimer("Vehicles")
--------------------- ---------------------
----- Load Jobs ----- ----- Load Jobs -----
--------------------- ---------------------
-- Jobs loading based on framework
if checkExists(Exports.QBXExport) then
jobResource = Exports.QBXExport
cache.Jobs, cache.Gangs = exports[Exports.QBXExport]:GetJobs(), exports[Exports.QBXExport]:GetGangs()
elseif checkExists(Exports.QBExport) then local jobFunc = {
jobResource = Exports.QBExport
cache.Jobs, cache.Gangs = exports[Exports.QBExport]:GetCoreObject().Shared.Jobs, exports[Exports.QBExport]:GetCoreObject().Shared.Gangs
elseif checkExists(Exports.OXCoreExport) then { script = Exports.QBXExport,
jobResource = Exports.OXCoreExport cacheJob = function()
while not MySQL do Wait(1000) end cache.Jobs, cache.Gangs = exports[Exports.QBXExport]:GetJobs(), exports[Exports.QBXExport]:GetGangs()
local tempJobs = MySQL.query.await('SELECT * FROM `ox_groups`') end,
local tempGrades = MySQL.query.await('SELECT * FROM `ox_group_grades`') },
local gradeMap = {} { script = Exports.QBExport,
for _, grade in pairs(tempGrades) do cacheJob = function()
gradeMap[grade.group] = gradeMap[grade.group] or {} Core = exports[Exports.QBExport]:GetCoreObject()
gradeMap[grade.group][grade.grade] = { name = grade.label } cache.Jobs, cache.Gangs = Core.Shared.Jobs, Core.Shared.Gangs
end end,
for _, job in pairs(tempJobs) do },
cache.Jobs[job.name] = { { script = Exports.OXCoreExport,
label = job.label, cacheJob = function()
grades = gradeMap[job.name] or {} while not MySQL do Wait(100) end
} local tempJobs = MySQL.query.await('SELECT * FROM `ox_groups`')
end local tempGrades = MySQL.query.await('SELECT * FROM `ox_group_grades`')
cache.Gangs = cache.Jobs local gradeMap = {}
for _, grade in pairs(tempGrades) do
elseif checkExists(Exports.ESXExport) then gradeMap[grade.group] = gradeMap[grade.group] or {}
jobResource = Exports.ESXExport gradeMap[grade.group][grade.grade] = { name = grade.label }
ESX = exports[Exports.ESXExport]:getSharedObject()
cache.Jobs = ESX.GetJobs()
while not next(cache.Jobs) do
Wait(100)
cache.Jobs = ESX.GetJobs()
end
for Role, Grades in pairs(cache.Jobs) do
-- Check for if user has added grades
if Grades.grades == nil or not next(Grades.grades) then
goto continue
end
for grade, info in pairs(Grades.grades) do
if info.label and info.label:find("[Bb]oss") then
cache.Jobs[Role].grades[grade].isBoss = true
goto continue
end end
end for _, job in pairs(tempJobs) do
local highestGrade = nil cache.Jobs[job.name] = {
for k in pairs(Grades.grades) do label = job.label,
local num = tonumber(k) grades = gradeMap[job.name] or {}
if num and (not highestGrade or num > highestGrade) then }
highestGrade = num
end end
end cache.Gangs = cache.Jobs
end,
},
{ script = Exports.ESXExport,
cacheJob = function()
ESX = ESX or exports[Exports.ESXExport]:getSharedObject()
cache.Jobs = ESX.GetJobs()
while not next(cache.Jobs) do
Wait(100)
cache.Jobs = ESX.GetJobs()
end
for Role, Grades in pairs(cache.Jobs) do
-- Check for if user has added grades
if Grades.grades == nil or not next(Grades.grades) then
goto continue
end
for grade, info in pairs(Grades.grades) do
if info.label and info.label:find("[Bb]oss") then
cache.Jobs[Role].grades[grade].isBoss = true
goto continue
end
end
local highestGrade = nil
for k in pairs(Grades.grades) do
local num = tonumber(k)
if num and (not highestGrade or num > highestGrade) then
highestGrade = num
end
end
if highestGrade then if highestGrade then
cache.Jobs[Role].grades[tostring(highestGrade)].isBoss = true cache.Jobs[Role].grades[tostring(highestGrade)].isBoss = true
end end
::continue:: ::continue::
end
cache.Gangs = cache.Jobs
end,
},
{ script = Exports.RSGExport,
cacheJob = function()
Core = exports[Exports.RSGExport]:GetCoreObject()
cache.Jobs, cache.Gangs = Core.Shared.Jobs, Core.Shared.Gangs
end,
},
{ script = Exports.VorpExport,
cacheJob = function()
cache.Jobs = { ["unkown"] = {} }
cache.Gangs = cache.Jobs
end,
},
}
for i = 1, #jobFunc do
local data = jobFunc[i]
if checkExists(data.script) then
waitStarted(data.script) -- Wait for detected script to start fully
data.cacheJob() -- run tablized function for core
jobResource = data.script -- Grab script name to announce later
endTimer("Jobs") -- end timer
break -- break loop so it doesn't keep checking
end end
cache.Gangs = cache.Jobs
elseif checkExists(Exports.RSGExport) then
jobResource = Exports.RSGExport
cache.Jobs, cache.Gangs = exports[Exports.RSGExport]:GetCoreObject().Shared.Jobs, exports[Exports.RSGExport]:GetCoreObject().Shared.Gangs
end end
endTimer("Jobs")
-- Fallback if nil or empty -- Fallback if nil or empty
if cache.Items == nil or not next(cache.Items) then if cache.Items == nil or not next(cache.Items) then
@@ -402,10 +483,8 @@ for script, data in pairs(invWeightTable) do
if checkExists(script) then if checkExists(script) then
if script == Exports.QBInv and GetResourceState(Exports.JPRInv):find("start") then goto skip end if script == Exports.QBInv and GetResourceState(Exports.JPRInv):find("start") then goto skip end
while GetResourceState(script) ~= "started" and GetResourceState(script) ~= "stopped" do waitStartedOrStopped(script)
Wait(100)
print("Waiting for script start")
end
local attempts = data.fallback or { data } local attempts = data.fallback or { data }
local lookup, used, err local lookup, used, err

View File

@@ -12,7 +12,7 @@ if isServer() then
local src = source local src = source
local token = keyGen()..keyGen()..keyGen()..keyGen() -- Use a secure random generator here local token = keyGen()..keyGen()..keyGen()..keyGen() -- Use a secure random generator here
--debugPrint(GetInvokingResource()) --debugPrint(GetInvokingResource())
if GetInvokingResource() and GetInvokingResource() ~= getScript() and GetInvokingResource() ~= "qb-core" then if GetInvokingResource() and GetInvokingResource() ~= getScript() and GetInvokingResource() ~= Exports.QBExport and GetInvokingResource() ~= Exports.VorpExport then
debugPrint("^1Error^7: ^1Possible exploit^7, ^1vital function was called from an external resource^7") debugPrint("^1Error^7: ^1Possible exploit^7, ^1vital function was called from an external resource^7")
return "" return ""
end end
@@ -45,8 +45,9 @@ if isServer() then
createCallback(getScript()..":callback:GetAuthEvent", function(source) createCallback(getScript()..":callback:GetAuthEvent", function(source)
local src = source local src = source
--debugPrint(GetInvokingResource())
if GetInvokingResource() and GetInvokingResource() ~= getScript() and GetInvokingResource() ~= "qb-core" then if GetInvokingResource() and GetInvokingResource() ~= getScript() and GetInvokingResource() ~= Exports.QBExport and GetInvokingResource() ~= Exports.VorpExport then
debugPrint("^1Error^7: ^1Possible exploit^7, ^1vital callback was called from an external resource^7") debugPrint("^1Error^7: ^1Possible exploit^7, ^1vital callback was called from an external resource^7")
return "" return ""
end end

View File

@@ -62,6 +62,9 @@ function onPlayerLoaded(func, onStart)
elseif isStarted(RSGExport) then elseif isStarted(RSGExport) then
onPlayerFramework = RSGExport onPlayerFramework = RSGExport
RegisterNetEvent('RSGCore:Client:OnPlayerLoaded', tempFunc) RegisterNetEvent('RSGCore:Client:OnPlayerLoaded', tempFunc)
elseif isStarted(VorpExport) then
onPlayerFramework = VorpExport
RegisterNetEvent("vorp_core:Client:OnPlayerSpawned", tempFunc)
end end
if onPlayerFramework ~= "" then if onPlayerFramework ~= "" then
@@ -174,6 +177,12 @@ function waitForLogin()
break break
end end
end end
elseif isStarted(VorpExport) then
-- For other frameworks, use LocalPlayer.state.isLoggedIn.
while not LocalPlayer.state.IsInSession and (GetGameTimer() - startTime) < timeout do
Wait(100)
end
loggedIn = LocalPlayer.state.IsInSession
else else
-- For other frameworks, use LocalPlayer.state.isLoggedIn. -- For other frameworks, use LocalPlayer.state.isLoggedIn.
while not LocalPlayer.state.isLoggedIn and (GetGameTimer() - startTime) < timeout do while not LocalPlayer.state.isLoggedIn and (GetGameTimer() - startTime) < timeout do

View File

@@ -37,6 +37,10 @@ function createCallback(callbackName, funct)
debugPrint("^6Bridge^7: ^2Registering ^4"..QBExport.." ^3Callback^7:", callbackName) debugPrint("^6Bridge^7: ^2Registering ^4"..QBExport.." ^3Callback^7:", callbackName)
Core = Core or exports[QBExport]:GetCoreObject() Core = Core or exports[QBExport]:GetCoreObject()
Core.Functions.CreateCallback(callbackName, adaptedFunction) Core.Functions.CreateCallback(callbackName, adaptedFunction)
elseif isStarted(VorpExport) then
debugPrint("^6Bridge^7: ^2Registering ^4"..VorpExport.." ^3Callback^7:", callbackName)
Core = Core or exports.vorp_core:GetCore()
Core.Callback.Register(callbackName, adaptedFunction)
elseif isStarted(ESXExport) then elseif isStarted(ESXExport) then
debugPrint("^6Bridge^7: ^2Registering ^4"..ESXExport.." ^3Callback^7:", callbackName) debugPrint("^6Bridge^7: ^2Registering ^4"..ESXExport.." ^3Callback^7:", callbackName)
ESX.RegisterServerCallback(callbackName, adaptedFunction) ESX.RegisterServerCallback(callbackName, adaptedFunction)
@@ -76,6 +80,13 @@ function triggerCallback(callbackName, ...)
end, ...) end, ...)
result = Citizen.Await(p) result = Citizen.Await(p)
Wait(10) Wait(10)
elseif isStarted(VorpExport) then
local p = promise.new()
Core.Callback.TriggerAwait(callbackName, function(cbResult)
p:resolve(cbResult)
end, ...)
result = Citizen.Await(p)
Wait(10)
elseif isStarted(ESXExport) then elseif isStarted(ESXExport) then
local p = promise.new() local p = promise.new()
ESX.TriggerServerCallback(callbackName, function(cbResult) ESX.TriggerServerCallback(callbackName, function(cbResult)

View File

@@ -22,6 +22,9 @@ OXInv, QBInv, PSInv, QSInv, CoreInv, CodeMInv, OrigenInv, TgiannInv, JPRInv =
Exports.JPRInv or "" Exports.JPRInv or ""
RSGExport, RSGInv = Exports.RSGExport or "", Exports.RSGInv or "" RSGExport, RSGInv = Exports.RSGExport or "", Exports.RSGInv or ""
VorpExport, VorpInv = Exports.VorpExport or "", Exports.VorpInv or ""
QBMenuExport = Exports.QBMenuExport or "" QBMenuExport = Exports.QBMenuExport or ""
QBTargetExport, OXTargetExport = Exports.QBTargetExport or "", Exports.OXTargetExport or "" QBTargetExport, OXTargetExport = Exports.QBTargetExport or "", Exports.OXTargetExport or ""
@@ -29,6 +32,8 @@ if isStarted(QBXExport) or isStarted(QBExport) then
Core = Core or exports[QBExport]:GetCoreObject() Core = Core or exports[QBExport]:GetCoreObject()
elseif isStarted(RSGExport) then elseif isStarted(RSGExport) then
Core = Core or exports[RSGExport]:GetCoreObject() Core = Core or exports[RSGExport]:GetCoreObject()
elseif isStarted(VorpExport) then
Core = Core or exports[VorpExport]:GetCore()
end end

View File

@@ -180,6 +180,7 @@ function GetPrintTime()
local hour, min, sec = os.date('%H'), os.date('%M'), os.date('%S') local hour, min, sec = os.date('%H'), os.date('%M'), os.date('%S')
return "^7("..string.format("%02d", hour)..":"..string.format("%02d", min)..":"..string.format("%02d", sec)..")" return "^7("..string.format("%02d", hour)..":"..string.format("%02d", min)..":"..string.format("%02d", sec)..")"
else else
if gameName == "rdr3" then return "" end
local _, _, _, hour, min, sec = GetLocalTime() local _, _, _, hour, min, sec = GetLocalTime()
return "^7("..string.format("%02d", hour)..":"..string.format("%02d", min)..":"..string.format("%02d", sec)..")" return "^7("..string.format("%02d", hour)..":"..string.format("%02d", min)..":"..string.format("%02d", sec)..")"
end end

View File

@@ -65,7 +65,6 @@ function makePed(data, coords, freeze, collision, scenario, anim, synced, fade)
model = data.model model = data.model
loadModel(data.model) loadModel(data.model)
ped = CreatePed(0, model, coords.x, coords.y, coords.z - 1.03, coords.w, synced and synced or false, false) ped = CreatePed(0, model, coords.x, coords.y, coords.z - 1.03, coords.w, synced and synced or false, false)
SetEntityAlpha(ped, 0, false)
-- Inheritance -- Inheritance
SetPedHeadBlendData(ped, data.custom.faceFather, data.custom.faceMother, data.custom.raceShape, data.custom.skinFather, data.custom.skinMother, data.custom.raceSkin, data.custom.faceMix or 0, data.custom.skinMix or 0, data.custom.raceMix or 0, false) SetPedHeadBlendData(ped, data.custom.faceFather, data.custom.faceMother, data.custom.raceShape, data.custom.skinFather, data.custom.skinMother, data.custom.raceSkin, data.custom.faceMix or 0, data.custom.skinMix or 0, data.custom.raceMix or 0, false)
@@ -145,7 +144,8 @@ function makePed(data, coords, freeze, collision, scenario, anim, synced, fade)
end end
unloadModel(model) unloadModel(model)
Peds[keyGen()..keyGen()] = ped Peds[keyGen()..keyGen()] = ped
if fade ~= false then if fade ~= false and gameName ~= "rdr3" then
SetEntityAlpha(ped, 0, false)
CreateThread(function() CreateThread(function()
fadeInEnt(ped) fadeInEnt(ped)
end) end)

View File

@@ -24,14 +24,14 @@ local distProps = {}
function makeProp(data, freeze, synced, fade) function makeProp(data, freeze, synced, fade)
loadModel(data.prop) loadModel(data.prop)
local prop = CreateObject(data.prop, data.coords.x, data.coords.y, data.coords.z-1.03, synced and synced or false, synced and synced or false, false) local prop = CreateObject(data.prop, data.coords.x, data.coords.y, data.coords.z-1.03, synced and synced or false, synced and synced or false, false)
SetEntityAlpha(veh, 0, false)
SetEntityHeading(prop, (data.coords.w or 0) + 180.0) SetEntityHeading(prop, (data.coords.w or 0) + 180.0)
FreezeEntityPosition(prop, freeze or false) FreezeEntityPosition(prop, freeze or false)
debugPrint("^6Bridge^7: ^1Prop ^2Created^7: '^6"..prop.."^7' | ^2Hash^7: ^7'^6"..data.prop.."^7' | ^2Coord^7: "..formatCoord(data.coords)) debugPrint("^6Bridge^7: ^1Prop ^2Created^7: '^6"..prop.."^7' | ^2Hash^7: ^7'^6"..data.prop.."^7' | ^2Coord^7: "..formatCoord(data.coords))
SetModelAsNoLongerNeeded(data.prop) SetModelAsNoLongerNeeded(data.prop)
Props[keyGen()..keyGen()] = prop Props[keyGen()..keyGen()] = prop
if fade ~= false then if fade ~= false and gameName ~= "rdr3" then
SetEntityAlpha(prop, 0, false)
CreateThread(function() CreateThread(function()
fadeInEnt(prop) fadeInEnt(prop)
end) end)

View File

@@ -30,7 +30,7 @@ function makeVeh(model, coords, synced, fade)
debugPrint("^6Bridge^7: ^1Veh ^2Created^7: '^6"..veh.."^7' | ^2Hash^7: ^7'^6"..model.."^7' | ^2Coord^7: "..formatCoord(coords)) debugPrint("^6Bridge^7: ^1Veh ^2Created^7: '^6"..veh.."^7' | ^2Hash^7: ^7'^6"..model.."^7' | ^2Coord^7: "..formatCoord(coords))
unloadModel(model) unloadModel(model)
Vehicles[#Vehicles + 1] = veh Vehicles[#Vehicles + 1] = veh
if fade ~= false then if fade ~= false and gameName ~= "rdr3" then
SetEntityAlpha(veh, 0, false) SetEntityAlpha(veh, 0, false)
CreateThread(function() CreateThread(function()
fadeInEnt(veh) fadeInEnt(veh)

View File

@@ -25,7 +25,12 @@ Exports = {
-- REDM -- REDM
RSGExport = "rsg-core", RSGExport = "rsg-core",
RSGInv = "rsg-inventory" RSGInv = "rsg-inventory",
VorpExport = "vorp_core",
VorpInv = "vorp_inventory",
VorpMenu = "vorp_menu",
} }
-- Required variables -- Required variables