Files
jim_bridge/shared/_loaders.lua
Jim Shield b46d734442 Testing a rework _loaders.lua
Uses more specific functions per framework now for player loading in and out and optimizes use of them
2025-09-24 12:29:48 +01:00

322 lines
11 KiB
Lua

--[[
Player & Resource Event Utility Functions
-------------------------------------------
This module provides functions to:
• Execute code when the player character is loaded or unloaded.
• Execute code on resource start and stop.
• Wait for the player to be logged in before proceeding.
]]
local onLoadLast = {} -- keyed by tostring(func)
local function _debouncedRun(func)
local key = tostring(func)
local now = GetGameTimer()
local last = onLoadLast[key] or -1e12
if (now - last) < 5000 then
debugPrint(("^6Bridge^7 ^3onPlayerLoaded^7 skipped — cooldown %dms remaining"):format(5000 - (now - last)))
return
end
onLoadLast[key] = now
CreateThread(function()
Wait(2000) -- keep your small delay
debugPrint("^6Bridge^7: ^2Executing onPlayerLoaded callback")
func()
end)
end
local frameworkLoadFunc = {
{ framework = Exports.QBXExport,
onPlayerLoaded =
function(func)
RegisterNetEvent('QBCore:Client:OnPlayerLoaded', func)
end,
onPlayerUnload =
function(func)
RegisterNetEvent('QBCore:Client:OnPlayerUnload', func)
end,
waitforLogin =
function(timeout)
local startTime = GetGameTimer()
while not LocalPlayer.state.isLoggedIn and (GetGameTimer() - startTime) < timeout do
Wait(100)
end
return LocalPlayer.state.isLoggedIn
end,
},
{ framework = Exports.QBExport,
onPlayerLoaded =
function(func)
RegisterNetEvent('QBCore:Client:OnPlayerLoaded', func)
end,
onPlayerUnload =
function(func)
RegisterNetEvent('QBCore:Client:OnPlayerUnload', func)
end,
waitforLogin =
function(timeout)
local startTime = GetGameTimer()
while not LocalPlayer.state.isLoggedIn and (GetGameTimer() - startTime) < timeout do
Wait(100)
end
return LocalPlayer.state.isLoggedIn
end,
},
{ framework = Exports.ESXExport,
onPlayerLoaded =
function(func)
RegisterNetEvent("esx:playerLoaded", function()
-- make sure shared has loaded (because sql)
if waitForSharedLoad() then func() end
end)
end,
onPlayerUnload =
function(func)
RegisterNetEvent("esx:onPlayerLogout", func)
end,
waitforLogin =
function(timeout)
local startTime = GetGameTimer()
while (GetGameTimer() - startTime) < timeout do
local playerData = ESX.GetPlayerData()
if playerData and playerData.job then
return true
end
Wait(100)
end
end,
},
{ framework = Exports.OXCoreExport,
onPlayerLoaded =
function(func)
RegisterNetEvent('ox:playerLoaded', func)
end,
onPlayerUnload =
function(func)
RegisterNetEvent('ox:playerLogout', func)
end,
waitforLogin =
function(timeout)
if OxPlayer["stateId"] then
return true
end
while not OxPlayer["stateId"] do
Wait(1000)
if OxPlayer.get["stateId"] then
return true
end
end
end,
},
{ framework = Exports.RSGExport,
onPlayerLoaded =
function(func)
RegisterNetEvent('RSGCore:Client:OnPlayerLoaded', func)
end,
onPlayerUnload =
function(func)
RegisterNetEvent('RSGCore:Client:OnPlayerUnload', func)
end,
waitforLogin =
function(timeout)
local startTime = GetGameTimer()
while not LocalPlayer.state.isLoggedIn and (GetGameTimer() - startTime) < timeout do
Wait(100)
end
return LocalPlayer.state.isLoggedIn
end,
},
{ framework = Exports.VorpExport,
onPlayerLoaded =
function(func)
RegisterNetEvent('vorp_core:Client:OnPlayerSpawned', func)
end,
onPlayerUnload =
function(func)
--??
end,
waitforLogin =
function(timeout)
local startTime = GetGameTimer()
while not LocalPlayer.state.IsInSession and (GetGameTimer() - startTime) < timeout do
Wait(100)
end
return LocalPlayer.state.IsInSession
end,
},
}
-------------------------------------------------------------
-- Player Loaded and Unloaded Events
-------------------------------------------------------------
--- Executes a function when the player character is loaded.
--- If onStart is true, the function will also run on resource start (after ensuring the player is logged in).
---
--- @param func function The function to execute when the player is loaded.
--- @param onStart boolean (optional) If true, also execute on resource start. Default is false.
--- @usage
--- ```lua
--- onPlayerLoaded(function()
--- print("Player logged in")
--- -- Your initialization code here.
--- end, true)
--- ```
function onPlayerLoaded(func, onStart)
if onStart then
onResourceStart(function()
if not waitForLogin() then return end
debugPrint("^6Bridge^7: ^3onResourceStart^7()^2 routed through ^3onPlayerLoaded^7()")
_debouncedRun(func)
end, true)
end
local handler = function()
_debouncedRun(func)
end
for i = 1, #frameworkLoadFunc do
local data = frameworkLoadFunc[i]
jsonPrint(data)
if isStarted(data.framework) then
debugPrint("^6Bridge^7: ^2Registering ^3"..data.framework.." ^5onPlayerLoaded^7()")
data.onPlayerLoaded(handler)
return
end
end
print("^1ERROR^7: ^1No supported core detected for onPlayerLoaded - Check starter.lua^7")
end
--- Executes a function when the player character is unloaded.
--- @param func function The function to execute when the player unloads.
--- @usage
--- ```lua
--- onPlayerUnload(function()
--- print("Player has logged out of their character")
--- -- Your cleanup code here.
--- end)
--- ```
function onPlayerUnload(func)
for i = 1, #frameworkLoadFunc do
local data = frameworkLoadFunc[i]
if isStarted(data.framework) then
debugPrint("^6Bridge^7: ^2Registering ^3"..data.framework.." ^5onPlayerUnload^7()")
data.onPlayerUnload(func)
return
end
end
print("^1ERROR^7: ^1No supported core detected for onPlayerUnload - Check starter.lua^7")
end
-------------------------------------------------------------
-- Resource Start and Stop Events
-------------------------------------------------------------
--- Executes a function when the resource starts.
--- @param func function The function to execute.
--- @param thisScript boolean (optional) If true, only runs when this resource starts (default true).
--- @usage
--- ```lua
--- onResourceStart(function()
--- print("Script ensured")
--- -- Initialization code on resource start.
--- end, true)
--- ```
local hasPrinted = false
function onResourceStart(func, thisScript)
debugPrint("^6Bridge^7: ^2Registering ^3onResourceStart^7()")
AddEventHandler('onResourceStart', function(resourceName)
if getScript() == resourceName and (thisScript or true) then
if waitForSharedLoad() then
if not hasPrinted then
debugPrint("^6Bridge^7: ^2Shared Load Detected^7.")
hasPrinted = true
end
func(resourceName)
end
end
end)
end
--- Executes a function when the resource stops.
--- @param func function The function to execute.
--- @param thisScript boolean (optional) If true, only runs when this resource stops (default true).
--- @usage
--- ```lua
--- onResourceStop(function()
--- -- Cleanup code here.
--- end, true)
--- ```
function onResourceStop(func, thisScript)
debugPrint("^6Bridge^7: ^2Registering ^3onResourceStop^7()")
AddEventHandler('onResourceStop', function(resourceName)
if getScript() == resourceName and (thisScript or true) then
func(resourceName)
end
end)
end
-------------------------------------------------------------
-- Wait for Login
-------------------------------------------------------------
--- Blocks execution until the player is logged in.
--- @usage
--- waitForLogin()
function waitForLogin()
for i = 1, #frameworkLoadFunc do
local data = frameworkLoadFunc[i]
if isStarted(data.framework) then
debugPrint("^6Bridge^7: ^2Waiting for ^3"..data.framework.."^2 player login^7.")
local result = data.waitforLogin(10000)
if result == true then
debugPrint("^6Bridge^7: ^3"..data.framework.."^2 Player Login Detected^7.")
else
print("^4Error^7: ^2Timeout reached while waiting for player login^7.")
end
return result
end
end
end
local messageShown = false
function waitForSharedLoad()
local timeout = GetGameTimer() + 900000 -- 15 minutes max wait (had to up this from 2 minutes because of slow servers)
local loop = 0
while ((not Jobs or not next(Jobs)) or
(not Items or not next(Items)) or
(not Vehicles or not next(Vehicles))
) and (timeout and GetGameTimer() < timeout) do
if loop >= 3 and not messageShown then
if (not Jobs or not next(Jobs)) then
print("^4Debug^7: ^2Waiting for ^7Jobs^2 to be loaded")
end
if (not Items or not next(Items)) then
print("^4Debug^7: ^2Waiting for ^7Items^2 to be loaded")
end
if (not Vehicles or not next(Vehicles)) then
print("^4Debug^7: ^2Waiting for ^7Vehicles^2 to be loaded")
end
messageShown = true
end
Wait(1000)
loop += 1
end
if Jobs and Items and Vehicles then
debugPrint("^6Bridge^7: ^2Jobs, Items, and Vehicles Loaded^7.")
return true
else
print("^4Error^7: ^1Timeout reached while waiting for shared load^7.")
return false
end
end