mirror of
https://github.com/CommunityOx/ox_lib.git
synced 2026-08-17 06:56:03 +01:00
Some people accidentally, mistakenly, and without any malicious intent forget to attribute code from this resource to its source. This change will hopefully assist people, so that they do not make that mistake again.
127 lines
3.7 KiB
Lua
127 lines
3.7 KiB
Lua
--[[
|
|
https://github.com/overextended/ox_lib
|
|
|
|
This file is licensed under LGPL-3.0 or higher <https://www.gnu.org/licenses/lgpl-3.0.en.html>
|
|
|
|
Copyright (c) 2025 Linden <https://github.com/thelindat/fivem>
|
|
]]
|
|
|
|
local pendingCallbacks = {}
|
|
local cbEvent = '__ox_cb_%s'
|
|
local callbackTimeout = GetConvarInt('ox:callbackTimeout', 300000)
|
|
|
|
RegisterNetEvent(cbEvent:format(cache.resource), function(key, ...)
|
|
local cb = pendingCallbacks[key]
|
|
|
|
if not cb then return end
|
|
|
|
pendingCallbacks[key] = nil
|
|
|
|
cb(...)
|
|
end)
|
|
|
|
---@param _ any
|
|
---@param event string
|
|
---@param playerId number
|
|
---@param cb function|false
|
|
---@param ... any
|
|
---@return ...
|
|
local function triggerClientCallback(_, event, playerId, cb, ...)
|
|
assert(DoesPlayerExist(playerId --[[@as string]]), ("target playerId '%s' does not exist"):format(playerId))
|
|
|
|
local key
|
|
|
|
repeat
|
|
key = ('%s:%s:%s'):format(event, math.random(0, 100000), playerId)
|
|
until not pendingCallbacks[key]
|
|
|
|
TriggerClientEvent('ox_lib:validateCallback', playerId, event, cache.resource, key)
|
|
TriggerClientEvent(cbEvent:format(event), playerId, cache.resource, key, ...)
|
|
|
|
---@type promise | false
|
|
local promise = not cb and promise.new()
|
|
|
|
pendingCallbacks[key] = function(response, ...)
|
|
if response == 'cb_invalid' then
|
|
response = ("callback '%s' does not exist"):format(event)
|
|
|
|
return promise and promise:reject(response) or error(response)
|
|
end
|
|
|
|
response = { response, ... }
|
|
|
|
if promise then
|
|
return promise:resolve(response)
|
|
end
|
|
|
|
if cb then
|
|
cb(table.unpack(response))
|
|
end
|
|
end
|
|
|
|
if promise then
|
|
SetTimeout(callbackTimeout, function() promise:reject(("callback event '%s' timed out"):format(key)) end)
|
|
|
|
return table.unpack(Citizen.Await(promise))
|
|
end
|
|
end
|
|
|
|
---@overload fun(event: string, playerId: number, cb: function, ...)
|
|
lib.callback = setmetatable({}, {
|
|
__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)
|
|
|
|
if cbType == 'table' and getmetatable(cb)?.__call then
|
|
cbType = 'function'
|
|
end
|
|
|
|
assert(cbType == 'function', ("expected argument 3 to have type 'function' (received %s)"):format(cbType))
|
|
end
|
|
|
|
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, ...)
|
|
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
|
|
|
|
return false
|
|
end
|
|
|
|
return result, ...
|
|
end
|
|
|
|
local pcall = pcall
|
|
|
|
---@param name string
|
|
---@param cb function
|
|
---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)
|
|
event = cbEvent:format(name)
|
|
|
|
lib.setValidCallback(name, true)
|
|
|
|
RegisterNetEvent(event, function(resource, key, ...)
|
|
TriggerClientEvent(cbEvent:format(resource), source, key, callbackResponse(pcall(cb, source, ...)))
|
|
end)
|
|
end
|
|
|
|
return lib.callback
|