forked from Simnation/Main
143 lines
4.4 KiB
Lua
143 lines
4.4 KiB
Lua
local Callback = {}
|
|
local CallbackRegistry = {}
|
|
|
|
-- Constants
|
|
local RESOURCE = GetCurrentResourceName() or 'unknown'
|
|
local EVENT_NAMES = {
|
|
CLIENT_TO_SERVER = RESOURCE .. ':CS:Callback',
|
|
SERVER_TO_CLIENT = RESOURCE .. ':SC:Callback',
|
|
CLIENT_RESPONSE = RESOURCE .. ':CSR:Callback',
|
|
SERVER_RESPONSE = RESOURCE .. ':SCR:Callback'
|
|
}
|
|
|
|
-- Utility functions
|
|
local function generateCallbackId(name)
|
|
return string.format('%s_%d', name, math.random(1000000, 9999999))
|
|
end
|
|
|
|
local function handleResponse(registry, name, callbackId, ...)
|
|
local data = registry[callbackId]
|
|
if not data then return end
|
|
|
|
if data.callback then
|
|
data.callback(...)
|
|
end
|
|
|
|
if data.promise then
|
|
data.promise:resolve({ ... })
|
|
end
|
|
|
|
registry[callbackId] = nil
|
|
end
|
|
|
|
local function triggerCallback(eventName, target, name, args, callback)
|
|
local callbackId = generateCallbackId(name)
|
|
local promise = promise.new()
|
|
|
|
CallbackRegistry[callbackId] = {
|
|
callback = callback,
|
|
promise = promise
|
|
}
|
|
|
|
if type(target) == 'table' then
|
|
for _, id in ipairs(target) do
|
|
TriggerClientEvent(eventName, tonumber(id), name, callbackId, table.unpack(args))
|
|
end
|
|
else
|
|
TriggerClientEvent(eventName, tonumber(target), name, callbackId, table.unpack(args))
|
|
end
|
|
|
|
if not callback then
|
|
local result = Citizen.Await(promise)
|
|
local returnResults = (result and type(result) == 'table' ) and result or {result}
|
|
return table.unpack(returnResults)
|
|
end
|
|
end
|
|
|
|
-- Server-side implementation
|
|
if IsDuplicityVersion() then
|
|
function Callback.Register(name, handler)
|
|
Callback[name] = handler
|
|
end
|
|
|
|
function Callback.Trigger(name, target, ...)
|
|
local args = { ... }
|
|
local callback = type(args[1]) == 'function' and table.remove(args, 1) or nil
|
|
return triggerCallback(EVENT_NAMES.SERVER_TO_CLIENT, target or -1, name, args, callback)
|
|
end
|
|
|
|
RegisterNetEvent(EVENT_NAMES.CLIENT_TO_SERVER, function(name, callbackId, ...)
|
|
if not name or not callbackId then return print(string.format("[%s] Warning: Invalid callback parameters - name: %s, callbackId: %s", RESOURCE, tostring(name), tostring(callbackId))) end
|
|
|
|
local handler = Callback[name]
|
|
if not handler then return end
|
|
|
|
local playerId = source
|
|
if not playerId or playerId == 0 then return print(string.format("[%s] Warning: Invalid source for callback '%s'", RESOURCE, name)) end
|
|
|
|
local result = table.pack(handler(playerId, ...))
|
|
TriggerClientEvent(EVENT_NAMES.CLIENT_RESPONSE, playerId, name, callbackId, table.unpack(result))
|
|
end)
|
|
|
|
RegisterNetEvent(EVENT_NAMES.SERVER_RESPONSE, function(name, callbackId, ...)
|
|
handleResponse(CallbackRegistry, name, callbackId, ...)
|
|
end)
|
|
|
|
-- Client-side implementation
|
|
else
|
|
local ClientCallbacks = {}
|
|
local ReboundCallbacks = {}
|
|
|
|
function Callback.Register(name, handler)
|
|
ClientCallbacks[name] = handler
|
|
end
|
|
|
|
function Callback.RegisterRebound(name, handler)
|
|
ReboundCallbacks[name] = handler
|
|
end
|
|
|
|
function Callback.Trigger(name, ...)
|
|
local args = { ... }
|
|
local callback = type(args[1]) == 'function' and table.remove(args, 1) or nil
|
|
|
|
local callbackId = generateCallbackId(name)
|
|
local promise = promise.new()
|
|
|
|
CallbackRegistry[callbackId] = {
|
|
callback = callback,
|
|
promise = promise
|
|
}
|
|
|
|
TriggerServerEvent(EVENT_NAMES.CLIENT_TO_SERVER, name, callbackId, table.unpack(args))
|
|
|
|
if not callback then
|
|
local result = Citizen.Await(promise)
|
|
return table.unpack(result)
|
|
end
|
|
end
|
|
|
|
RegisterNetEvent(EVENT_NAMES.CLIENT_RESPONSE, function(name, callbackId, ...)
|
|
if ReboundCallbacks[name] then
|
|
ReboundCallbacks[name](...)
|
|
end
|
|
handleResponse(CallbackRegistry, name, callbackId, ...)
|
|
end)
|
|
|
|
RegisterNetEvent(EVENT_NAMES.SERVER_TO_CLIENT, function(name, callbackId, ...)
|
|
local handler = ClientCallbacks[name]
|
|
if not handler then return end
|
|
|
|
local result = table.pack(handler(...))
|
|
TriggerServerEvent(EVENT_NAMES.SERVER_RESPONSE, name, callbackId, table.unpack(result))
|
|
end)
|
|
end
|
|
|
|
-- Exports
|
|
exports('Callback', Callback)
|
|
exports('RegisterCallback', Callback.Register)
|
|
exports('TriggerCallback', Callback.Trigger)
|
|
if not IsDuplicityVersion() then
|
|
exports('RegisterRebound', Callback.RegisterRebound)
|
|
end
|
|
|
|
return Callback
|