2024-05-03 15:49:33 +10:00
local pendingCallbacks = {}
2022-06-09 04:43:37 +10:00
local timers = {}
2024-05-03 15:49:33 +10:00
local cbEvent = '__ox_cb_%s'
2024-05-21 05:50:06 +10:00
local callbackTimeout = GetConvarInt ( 'ox:callbackTimeout' , 300000 )
2022-06-09 04:43:37 +10:00
2022-06-19 13:08:28 +10:00
RegisterNetEvent ( cbEvent : format ( cache.resource ), function ( key , ...)
2024-05-03 15:49:33 +10:00
local cb = pendingCallbacks [ key ]
pendingCallbacks [ key ] = nil
return cb and cb (...)
2022-06-09 04:43:37 +10:00
end )
2022-02-28 16:30:58 +11:00
---@param event string
2024-05-22 16:36:22 +10:00
---@param delay? number | false prevent the event from being called for the given time
2022-06-09 04:43:37 +10:00
local function eventTimer ( event , delay )
2024-05-03 15:49:33 +10:00
if delay and type ( delay ) == 'number' and delay > 0 then
local time = GetGameTimer ()
2022-06-09 04:43:37 +10:00
2024-05-03 15:49:33 +10:00
if ( timers [ event ] or 0 ) > time then
return false
end
2022-06-09 04:43:37 +10:00
2024-05-03 15:49:33 +10:00
timers [ event ] = time + delay
end
2022-06-09 04:43:37 +10:00
2024-05-03 15:49:33 +10:00
return true
2022-02-28 16:30:58 +11:00
end
2022-06-09 04:43:37 +10:00
---@param _ any
---@param event string
2024-05-22 16:36:22 +10:00
---@param delay number | false | nil
---@param cb function | false
2022-08-08 17:16:57 +10:00
---@param ... any
2023-02-06 13:22:19 +11:00
---@return ...
2022-06-09 04:43:37 +10:00
local function triggerServerCallback ( _ , event , delay , cb , ...)
2024-05-03 15:49:33 +10:00
if not eventTimer ( event , delay ) then return end
2022-06-09 04:43:37 +10:00
2024-05-03 15:49:33 +10:00
local key
2022-06-09 04:43:37 +10:00
2024-05-03 15:49:33 +10:00
repeat
key = ( '%s:%s' ): format ( event , math.random ( 0 , 100000 ))
until not pendingCallbacks [ key ]
2022-06-09 04:43:37 +10:00
2024-05-03 15:49:33 +10:00
TriggerServerEvent ( cbEvent : format ( event ), cache.resource , key , ...)
2022-06-09 04:43:37 +10:00
2024-05-03 15:49:33 +10:00
---@type promise | false
local promise = not cb and promise.new ()
2022-06-09 04:43:37 +10:00
2024-05-03 15:49:33 +10:00
pendingCallbacks [ key ] = function ( response , ...)
2022-12-11 12:39:40 +11:00
response = { response , ... }
2022-06-09 04:43:37 +10:00
2024-05-03 15:49:33 +10:00
if promise then
return promise : resolve ( response )
end
2022-06-09 04:43:37 +10:00
2022-12-11 12:39:40 +11:00
if cb then
cb ( table.unpack ( response ))
2022-10-25 03:02:44 +11:00
end
2024-05-03 15:49:33 +10:00
end
2022-06-09 04:43:37 +10:00
2024-05-03 15:49:33 +10:00
if promise then
SetTimeout ( callbackTimeout , function () promise : reject (( "callback event '%s' timed out" ): format ( key )) end )
return table.unpack ( Citizen.Await ( promise ))
end
2022-02-28 16:30:58 +11:00
end
2022-09-14 16:12:43 +10:00
---@overload fun(event: string, delay: number | false, cb: function, ...)
2022-09-14 00:50:27 +10:00
lib.callback = setmetatable ({}, {
2024-05-22 16:36:22 +10:00
__call = function ( _ , event , delay , cb , ...)
2024-05-23 09:41:24 +10:00
if not cb then
warn (( "callback event '%s' does not have a function to callback to and will instead await \n use lib.callback.await or a regular event to remove this warning" )
: format ( event ))
else
local cbType = type ( cb )
2024-05-22 16:36:22 +10:00
2025-01-20 02:10:02 +11:00
if cbType == 'table' and getmetatable ( cb ) ? . __call then
cbType = 'function'
end
2024-05-23 09:41:24 +10:00
assert ( cbType == 'function' , ( "expected argument 3 to have type 'function' (received %s)" ): format ( cbType ))
end
2024-05-22 16:36:22 +10:00
return triggerServerCallback ( _ , event , delay , cb , ...)
end
2022-06-09 04:43:37 +10:00
})
2022-02-28 16:30:58 +11:00
---@param event string
2023-09-15 22:32:55 +10:00
---@param delay? number | false prevent the event from being called for the given time.
---Sends an event to the server and halts the current thread until a response is returned.
2024-05-22 16:36:22 +10:00
---@diagnostic disable-next-line: duplicate-set-field
2022-09-14 00:50:27 +10:00
function lib . callback . await ( event , delay , ...)
2024-05-03 15:49:33 +10:00
return triggerServerCallback ( nil , event , delay , false , ...)
2022-02-28 16:30:58 +11:00
end
2022-08-25 18:49:07 +10:00
local function callbackResponse ( success , result , ...)
2024-05-03 15:49:33 +10:00
if not success then
if result then
return print (( '^1SCRIPT ERROR: %s^0 \n %s' ): format ( result ,
Citizen.InvokeNative ( ` FORMAT_STACK_TRACE ` & 0xFFFFFFFF , nil , 0 , Citizen.ResultAsString ()) or '' ))
end
2022-08-25 18:49:07 +10:00
2024-05-03 15:49:33 +10:00
return false
end
2022-08-25 18:49:07 +10:00
2024-05-03 15:49:33 +10:00
return result , ...
2022-08-25 18:49:07 +10:00
end
local pcall = pcall
2022-06-09 05:15:27 +10:00
---@param name string
---@param cb function
2024-05-22 16:36:22 +10:00
---Registers an event handler and callback function to respond to server requests.
---@diagnostic disable-next-line: duplicate-set-field
2022-09-14 00:50:27 +10:00
function lib . callback . register ( name , cb )
2024-05-03 15:49:33 +10:00
RegisterNetEvent ( cbEvent : format ( name ), function ( resource , key , ...)
TriggerServerEvent ( cbEvent : format ( resource ), key , callbackResponse ( pcall ( cb , ...)))
end )
2022-06-09 05:15:27 +10:00
end
2022-09-14 00:50:27 +10:00
return lib.callback