From 76fcc007c4a7ac3d25df71904fc0687ab3543eb0 Mon Sep 17 00:00:00 2001 From: Linden <65407488+thelindat@users.noreply.github.com> Date: Thu, 9 Jun 2022 05:15:27 +1000 Subject: [PATCH] feat(callback): client callback Allow the client to listen for and respond to server requests. Basically just copy-paste and swap the two. --- imports/callback/client.lua | 11 ++++++++ imports/callback/server.lua | 53 +++++++++++++++++++++++++++++++++++-- 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/imports/callback/client.lua b/imports/callback/client.lua index b79b1af..ca1f90c 100644 --- a/imports/callback/client.lua +++ b/imports/callback/client.lua @@ -69,4 +69,15 @@ function callback.await(event, delay, ...) return triggerServerCallback(_, event, delay, false, ...) end +---@param name string +---@param cb function +--- Registers an event handler and callback function to respond to server requests. +function callback.register(name, cb) + name = ('__cb_%s'):format(name) + + RegisterNetEvent(name, function(key, ...) + TriggerServerEvent(cbEvent, key, { cb(...) }) + end) +end + return callback diff --git a/imports/callback/server.lua b/imports/callback/server.lua index 9439527..1071673 100644 --- a/imports/callback/server.lua +++ b/imports/callback/server.lua @@ -1,13 +1,62 @@ -local callback = {} +local events = {} local cbEvent = ('__cb_%s'):format(cache.resource) +RegisterNetEvent(cbEvent, function(key, ...) + local cb = events[key] + return cb and cb(...) +end) + +---@param _ any +---@param event string +---@param playerId number +---@param cb function +---@param ... unknown +---@return unknown +local function triggerClientCallback(_, event, playerId, cb, ...) + local key + + repeat + key = ('%s:%s:%s'):format(event, math.random(0, 100000), playerId) + until not events[key] + + TriggerClientEvent(('__cb_%s'):format(event), playerId, key, ...) + + local promise = not cb and promise.new() + + events[key] = function(response) + events[key] = nil + + if promise then + return promise:resolve(response) + end + + cb(table.unpack(response)) + end + + if promise then + return table.unpack(Citizen.Await(promise)) + end +end + +---@overload fun(event: string, playerId: number, cb: function, ...) +local callback = setmetatable({}, { + __call = triggerClientCallback +}) + +---@param event string +---@param playerId number +--- Sends an event to a client and halts the current thread until a response is returned. +function callback.await(event, playerId, ...) + return triggerClientCallback(_, event, playerId, false, ...) +end + ---@param name string ---@param cb function --- Registers an event handler and callback function to respond to client requests. function callback.register(name, cb) name = ('__cb_%s'):format(name) - RegisterServerEvent(name, function(key, ...) + RegisterNetEvent(name, function(key, ...) TriggerClientEvent(cbEvent, source, key, { cb(source, ...) }) end) end