1
0
Fork 0
forked from Simnation/Main
Main/resources/[carscripts]/community_bridge/lib/utility/shared/callbacks.lua
2025-08-06 16:37:06 +02:00

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