Files
ox_lib/imports/callback/server.lua
T

101 lines
3.0 KiB
Lua
Raw Normal View History

local pendingCallbacks = {}
local cbEvent = '__ox_cb_%s'
local callbackTimeout = GetConvarInt('ox:callbackTimeout', 300000)
2022-02-28 16:30:58 +11:00
RegisterNetEvent(cbEvent:format(cache.resource), function(key, ...)
2024-05-22 16:36:22 +10:00
local cb = pendingCallbacks[key]
pendingCallbacks[key] = nil
2024-05-22 16:36:22 +10:00
return cb and cb(...)
2022-06-09 05:15:27 +10:00
end)
---@param _ any
---@param event string
---@param playerId number
2022-08-08 17:16:57 +10:00
---@param cb function|false
---@param ... any
2023-02-06 13:22:19 +11:00
---@return ...
2022-06-09 05:15:27 +10:00
local function triggerClientCallback(_, event, playerId, cb, ...)
2024-05-22 16:36:22 +10:00
assert(DoesPlayerExist(playerId --[[@as string]]), ("target playerId '%s' does not exist"):format(playerId))
2022-06-09 05:15:27 +10:00
2024-05-22 16:36:22 +10:00
local key
2022-06-09 05:15:27 +10:00
2024-05-22 16:36:22 +10:00
repeat
key = ('%s:%s:%s'):format(event, math.random(0, 100000), playerId)
until not pendingCallbacks[key]
2022-06-09 05:15:27 +10:00
2024-05-22 16:36:22 +10:00
TriggerClientEvent(cbEvent:format(event), playerId, cache.resource, key, ...)
2022-06-09 05:15:27 +10:00
2024-05-22 16:36:22 +10:00
---@type promise | false
local promise = not cb and promise.new()
pendingCallbacks[key] = function(response, ...)
response = { response, ... }
2022-06-09 05:15:27 +10:00
2024-05-22 16:36:22 +10:00
if promise then
return promise:resolve(response)
end
2022-06-09 05:15:27 +10:00
if cb then
cb(table.unpack(response))
end
2024-05-22 16:36:22 +10:00
end
2022-06-09 05:15:27 +10:00
2024-05-22 16:36:22 +10:00
if promise then
SetTimeout(callbackTimeout, function() promise:reject(("callback event '%s' timed out"):format(key)) end)
2024-05-22 16:36:22 +10:00
return table.unpack(Citizen.Await(promise))
end
2022-06-09 05:15:27 +10:00
end
---@overload fun(event: string, playerId: number, cb: function, ...)
2022-09-14 00:50:27 +10:00
lib.callback = setmetatable({}, {
2024-05-22 16:36:22 +10: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\nuse 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
assert(cbType == 'function', ("expected argument 3 to have type 'function' (received %s)"):format(cbType))
end
2024-05-22 16:36:22 +10:00
return triggerClientCallback(_, event, playerId, cb, ...)
end
2022-06-09 05:15:27 +10:00
})
---@param event string
---@param playerId number
--- Sends an event to a client 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, playerId, ...)
2024-05-22 16:36:22 +10:00
return triggerClientCallback(nil, event, playerId, false, ...)
2022-06-09 05:15:27 +10:00
end
2022-08-25 18:49:07 +10:00
local function callbackResponse(success, result, ...)
2024-05-22 16:36:22 +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-22 16:36:22 +10:00
return false
end
2022-08-25 18:49:07 +10:00
2024-05-22 16:36:22 +10:00
return result, ...
2022-08-25 18:49:07 +10:00
end
local pcall = pcall
2022-02-28 16:30:58 +11:00
---@param name string
2022-03-10 14:23:25 +00:00
---@param cb function
2024-05-22 16:36:22 +10:00
---Registers an event handler and callback function to respond to client requests.
---@diagnostic disable-next-line: duplicate-set-field
2022-09-14 00:50:27 +10:00
function lib.callback.register(name, cb)
2024-05-22 16:36:22 +10:00
RegisterNetEvent(cbEvent:format(name), function(resource, key, ...)
TriggerClientEvent(cbEvent:format(resource), source, key, callbackResponse(pcall(cb, source, ...)))
end)
2022-02-28 16:30:58 +11:00
end
return lib.callback