2024-12-30 10:15:34 +00:00
local pendingCallbacks = { }
local cbEvent = ' __ox_cb_%s '
local callbackTimeout = GetConvarInt ( ' ox:callbackTimeout ' , 300000 )
2024-12-29 20:02:43 +00:00
RegisterNetEvent ( cbEvent : format ( cache.resource ) , function ( key , ... )
2024-12-30 10:15:34 +00:00
local cb = pendingCallbacks [ key ]
pendingCallbacks [ key ] = nil
return cb and cb ( ... )
2024-12-29 20:02:43 +00:00
end )
---@param _ any
---@param event string
---@param playerId number
---@param cb function|false
---@param ... any
---@return ...
local function triggerClientCallback ( _ , event , playerId , cb , ... )
2024-12-30 10:15:34 +00:00
assert ( DoesPlayerExist ( playerId --[[@as string]] ) , ( " target playerId '%s' does not exist " ) : format ( playerId ) )
local key
2024-12-29 20:02:43 +00:00
2024-12-30 10:15:34 +00:00
repeat
key = ( ' %s:%s:%s ' ) : format ( event , math.random ( 0 , 100000 ) , playerId )
until not pendingCallbacks [ key ]
2024-12-29 20:02:43 +00:00
2024-12-30 10:15:34 +00:00
TriggerClientEvent ( cbEvent : format ( event ) , playerId , cache.resource , key , ... )
2024-12-29 20:02:43 +00:00
2024-12-30 10:15:34 +00:00
---@type promise | false
local promise = not cb and promise.new ( )
2024-12-29 20:02:43 +00:00
2024-12-30 10:15:34 +00:00
pendingCallbacks [ key ] = function ( response , ... )
2024-12-29 20:02:43 +00:00
response = { response , ... }
2024-12-30 10:15:34 +00:00
if promise then
return promise : resolve ( response )
end
2024-12-29 20:02:43 +00:00
if cb then
cb ( table.unpack ( response ) )
end
2024-12-30 10:15:34 +00:00
end
2024-12-29 20:02:43 +00:00
2024-12-30 10:15:34 +00:00
if promise then
SetTimeout ( callbackTimeout , function ( ) promise : reject ( ( " callback event '%s' timed out " ) : format ( key ) ) end )
return table.unpack ( Citizen.Await ( promise ) )
end
2024-12-29 20:02:43 +00:00
end
---@overload fun(event: string, playerId: number, cb: function, ...)
lib.callback = setmetatable ( { } , {
2024-12-30 10:15:34 +00:00
__call = function ( _ , event , playerId , cb , ... )
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 )
assert ( cbType == ' function ' , ( " expected argument 3 to have type 'function' (received %s) " ) : format ( cbType ) )
end
return triggerClientCallback ( _ , event , playerId , cb , ... )
end
2024-12-29 20:02:43 +00:00
} )
---@param event string
---@param playerId number
--- Sends an event to a client and halts the current thread until a response is returned.
2024-12-30 10:15:34 +00:00
---@diagnostic disable-next-line: duplicate-set-field
2024-12-29 20:02:43 +00:00
function lib . callback . await ( event , playerId , ... )
2024-12-30 10:15:34 +00:00
return triggerClientCallback ( nil , event , playerId , false , ... )
2024-12-29 20:02:43 +00:00
end
local function callbackResponse ( success , result , ... )
2024-12-30 10:15:34 +00: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
2024-12-29 20:02:43 +00:00
2024-12-30 10:15:34 +00:00
return false
end
2024-12-29 20:02:43 +00:00
2024-12-30 10:15:34 +00:00
return result , ...
2024-12-29 20:02:43 +00:00
end
local pcall = pcall
---@param name string
---@param cb function
2024-12-30 10:15:34 +00:00
---Registers an event handler and callback function to respond to client requests.
---@diagnostic disable-next-line: duplicate-set-field
2024-12-29 20:02:43 +00:00
function lib . callback . register ( name , cb )
2024-12-30 10:15:34 +00:00
RegisterNetEvent ( cbEvent : format ( name ) , function ( resource , key , ... )
TriggerClientEvent ( cbEvent : format ( resource ) , source , key , callbackResponse ( pcall ( cb , source , ... ) ) )
end )
2024-12-29 20:02:43 +00:00
end
return lib.callback