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
 | 
