diff --git a/imports/callback/client.lua b/imports/callback/client.lua index aaafb90..6535bda 100644 --- a/imports/callback/client.lua +++ b/imports/callback/client.lua @@ -11,7 +11,7 @@ RegisterNetEvent(cbEvent:format(cache.resource), function(key, ...) end) ---@param event string ----@param delay number | false prevent the event from being called for the given time +---@param delay? number | false prevent the event from being called for the given time local function eventTimer(event, delay) if delay and type(delay) == 'number' and delay > 0 then local time = GetGameTimer() @@ -28,8 +28,8 @@ end ---@param _ any ---@param event string ----@param delay number | false ----@param cb function|false +---@param delay number | false | nil +---@param cb function | false ---@param ... any ---@return ... local function triggerServerCallback(_, event, delay, cb, ...) @@ -67,12 +67,19 @@ end ---@overload fun(event: string, delay: number | false, cb: function, ...) lib.callback = setmetatable({}, { - __call = triggerServerCallback + __call = function(_, event, delay, cb, ...) + local cbType = type(cb) + + assert(cbType == 'function', ("expected argument 3 to have type 'function' (received %s)"):format(cbType)) + + return triggerServerCallback(_, event, delay, cb, ...) + end }) ---@param event string ---@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. +---@diagnostic disable-next-line: duplicate-set-field function lib.callback.await(event, delay, ...) return triggerServerCallback(nil, event, delay, false, ...) end @@ -94,7 +101,8 @@ local pcall = pcall ---@param name string ---@param cb function ---- Registers an event handler and callback function to respond to server requests. +---Registers an event handler and callback function to respond to server requests. +---@diagnostic disable-next-line: duplicate-set-field function lib.callback.register(name, cb) RegisterNetEvent(cbEvent:format(name), function(resource, key, ...) TriggerServerEvent(cbEvent:format(resource), key, callbackResponse(pcall(cb, ...))) diff --git a/imports/callback/server.lua b/imports/callback/server.lua index 718cc07..65eef3e 100644 --- a/imports/callback/server.lua +++ b/imports/callback/server.lua @@ -3,10 +3,10 @@ local cbEvent = '__ox_cb_%s' local callbackTimeout = GetConvarInt('ox:callbackTimeout', 300000) RegisterNetEvent(cbEvent:format(cache.resource), function(key, ...) - local cb = pendingCallbacks[key] + local cb = pendingCallbacks[key] pendingCallbacks[key] = nil - return cb and cb(...) + return cb and cb(...) end) ---@param _ any @@ -16,71 +16,80 @@ end) ---@param ... any ---@return ... local function triggerClientCallback(_, event, playerId, cb, ...) - local key + assert(DoesPlayerExist(playerId --[[@as string]]), ("target playerId '%s' does not exist"):format(playerId)) - repeat - key = ('%s:%s:%s'):format(event, math.random(0, 100000), playerId) - until not pendingCallbacks[key] + local key - TriggerClientEvent(cbEvent:format(event), playerId, cache.resource, key, ...) + repeat + key = ('%s:%s:%s'):format(event, math.random(0, 100000), playerId) + until not pendingCallbacks[key] - ---@type promise | false - local promise = not cb and promise.new() + TriggerClientEvent(cbEvent:format(event), playerId, cache.resource, key, ...) - pendingCallbacks[key] = function(response, ...) + ---@type promise | false + local promise = not cb and promise.new() + + pendingCallbacks[key] = function(response, ...) response = { response, ... } - if promise then - return promise:resolve(response) - end + if promise then + return promise:resolve(response) + end if cb then cb(table.unpack(response)) end - end + end - if promise then + if promise then SetTimeout(callbackTimeout, function() promise:reject(("callback event '%s' timed out"):format(key)) end) - return table.unpack(Citizen.Await(promise)) - end + return table.unpack(Citizen.Await(promise)) + end end ---@overload fun(event: string, playerId: number, cb: function, ...) lib.callback = setmetatable({}, { - __call = triggerClientCallback + __call = function(_, event, playerId, cb, ...) + local cbType = type(cb) + + assert(cbType == 'function', ("expected argument 3 to have type 'function' (received %s)"):format(cbType)) + + return triggerClientCallback(_, event, playerId, cb, ...) + end }) ---@param event string ---@param playerId number --- Sends an event to a client and halts the current thread until a response is returned. +---@diagnostic disable-next-line: duplicate-set-field function lib.callback.await(event, playerId, ...) - return triggerClientCallback(nil, event, playerId, false, ...) + return triggerClientCallback(nil, event, playerId, false, ...) end local function callbackResponse(success, result, ...) - 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 + 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 - return false - end + return false + end - return result, ... + return result, ... end local pcall = pcall ---@param name string ---@param cb function ---- Registers an event handler and callback function to respond to client requests. +---Registers an event handler and callback function to respond to client requests. +---@diagnostic disable-next-line: duplicate-set-field function lib.callback.register(name, cb) - RegisterNetEvent(cbEvent:format(name), function(resource, key, ...) - TriggerClientEvent(cbEvent:format(resource), source, key, callbackResponse(pcall(cb, source, ...))) - end) + RegisterNetEvent(cbEvent:format(name), function(resource, key, ...) + TriggerClientEvent(cbEvent:format(resource), source, key, callbackResponse(pcall(cb, source, ...))) + end) end return lib.callback - -