From 532070b72dd86667c46c8845603bcb14f464477a Mon Sep 17 00:00:00 2001 From: Mirow Date: Tue, 1 Apr 2025 17:56:50 +0200 Subject: [PATCH 1/3] feat(callback): add `AwaitClientCallback` function --- .../es_extended/client/modules/callback.lua | 47 +++++++++---------- .../es_extended/server/modules/callback.lua | 36 +++++++++++++- 2 files changed, 57 insertions(+), 26 deletions(-) diff --git a/[core]/es_extended/client/modules/callback.lua b/[core]/es_extended/client/modules/callback.lua index 6bd2d758..85facbb7 100644 --- a/[core]/es_extended/client/modules/callback.lua +++ b/[core]/es_extended/client/modules/callback.lua @@ -14,8 +14,25 @@ Callbacks.id = 0 -- MARK: Internal Functions -- ============================================= -function Callbacks:Trigger(event, cb, invoker, ...) +function Callbacks:Register(name, resource, cb) + self.storage[name] = { + resource = resource, + cb = cb + } +end + +function Callbacks:Execute(cb, id, ...) + local success, errorString = pcall(cb, ...) + + if not success then + print(("[^1ERROR^7] Failed to execute Callback with RequestId: ^5%s^7"):format(id)) + error(errorString) + return + end +end + +function Callbacks:Trigger(event, cb, invoker, ...) self.requests[self.id] = { await = type(cb) == "boolean", cb = cb or promise:new() @@ -29,16 +46,6 @@ function Callbacks:Trigger(event, cb, invoker, ...) return table.cb end -function Callbacks:Execute(cb, id, ...) - local success, errorString = pcall(cb, ...) - - if not success then - print(("[^1ERROR^7] Failed to execute Callback with RequestId: ^5%s^7"):format(id)) - error(errorString) - return - end -end - function Callbacks:ServerRecieve(requestId, invoker, ...) if not self.requests[requestId] then return error(("Server Callback with requestId ^5%s^1 Was Called by ^5%s^1 but does not exist."):format(requestId, invoker)) @@ -49,21 +56,13 @@ function Callbacks:ServerRecieve(requestId, invoker, ...) self.requests[requestId] = nil if callback.await then - callback.cb:resolve({...}) + callback.cb:resolve({ ... }) else self:Execute(callback.cb, requestId, ...) end end -function Callbacks:Register(name, resource, cb) - self.storage[name] = { - resource = resource, - cb = cb - } -end - function Callbacks:ClientRecieve(eventName, requestId, invoker, ...) - if not self.storage[eventName] then return error(("Client Callback with requestId ^5%s^1 Was Called by ^5%s^1 but does not exist."):format(eventName, invoker)) end @@ -130,14 +129,14 @@ end -- MARK: Events -- ============================================= -ESX.SecureNetEvent("esx:triggerClientCallback", function(...) - Callbacks:ClientRecieve(...) -end) - ESX.SecureNetEvent("esx:serverCallback", function(...) Callbacks:ServerRecieve(...) end) +ESX.SecureNetEvent("esx:triggerClientCallback", function(...) + Callbacks:ClientRecieve(...) +end) + AddEventHandler("onResourceStop", function(resource) for k, v in pairs(Callbacks.storage) do if v.resource == resource then diff --git a/[core]/es_extended/server/modules/callback.lua b/[core]/es_extended/server/modules/callback.lua index 3301e6a6..fc89a855 100644 --- a/[core]/es_extended/server/modules/callback.lua +++ b/[core]/es_extended/server/modules/callback.lua @@ -33,11 +33,17 @@ function Callbacks:Execute(cb, ...) end function Callbacks:Trigger(player, event, cb, invoker, ...) - self.requests[self.id] = cb + self.requests[self.id] = { + await = type(cb) == "boolean", + cb = cb or promise:new() + } + local table = self.requests[self.id] TriggerClientEvent("esx:triggerClientCallback", player, event, self.id, invoker, ...) self.id += 1 + + return table.cb end function Callbacks:ServerRecieve(player, event, requestId, invoker, ...) @@ -64,8 +70,12 @@ function Callbacks:RecieveClient(requestId, invoker, ...) local callback = self.requests[self.currentId] - self:Execute(callback, ...) self.requests[requestId] = nil + if callback.await then + callback.cb:resolve({ ... }) + else + self:Execute(callback.cb, ...) + end end -- ============================================= @@ -83,6 +93,28 @@ function ESX.TriggerClientCallback(player, eventName, callback, ...) Callbacks:Trigger(player, eventName, callback, invoker, ...) end +---@param player number playerId +---@param eventName string +---@param ... any +---@return any +function ESX.AwaitClientCallback(player, eventName, ...) + local invokingResource = GetInvokingResource() + local invoker = (invokingResource and invokingResource ~= "Unknown") and invokingResource or "es_extended" + + local p = Callbacks:Trigger(player, eventName, false, invoker, ...) + if not p then return end + + SetTimeout(15000, function() + if p.state == "pending" then + p:reject("Server Callback Timed Out") + end + end) + + Citizen.Await(p) + + return table.unpack(p.value) +end + ---@param eventName string ---@param callback function ---@return nil From aba21e2c036caa770cf81fb8e19745f1691253a6 Mon Sep 17 00:00:00 2001 From: Mirow Date: Fri, 4 Apr 2025 16:59:08 +0200 Subject: [PATCH 2/3] feat(paycheck): add event --- .../es_extended/server/modules/paycheck.lua | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/[core]/es_extended/server/modules/paycheck.lua b/[core]/es_extended/server/modules/paycheck.lua index 54881709..cb7de3a9 100644 --- a/[core]/es_extended/server/modules/paycheck.lua +++ b/[core]/es_extended/server/modules/paycheck.lua @@ -9,29 +9,30 @@ function StartPayCheck() local salary = (job == "unemployed" or onDuty) and xPlayer.job.grade_salary or ESX.Math.Round(xPlayer.job.grade_salary * Config.OffDutyPaycheckMultiplier) if xPlayer.paycheckEnabled then + TriggerEvent("esx:paycheckReceived", xPlayer.source, salary, job, jobLabel, onDuty) if salary > 0 then if job == "unemployed" then -- unemployed xPlayer.addAccountMoney("bank", salary, "Welfare Check") TriggerClientEvent("esx:showAdvancedNotification", player, TranslateCap("bank"), TranslateCap("received_paycheck"), TranslateCap("received_help", salary), "CHAR_BANK_MAZE", 9) if Config.LogPaycheck then ESX.DiscordLogFields("Paycheck", "Paycheck - Unemployment Benefits", "green", { - { name = "Player", value = xPlayer.name, inline = true }, - { name = "ID", value = xPlayer.source, inline = true }, - { name = "Amount", value = salary, inline = true }, + { name = "Player", value = xPlayer.name, inline = true }, + { name = "ID", value = xPlayer.source, inline = true }, + { name = "Amount", value = salary, inline = true }, }) end - elseif Config.EnableSocietyPayouts then -- possibly a society + elseif Config.EnableSocietyPayouts then -- possibly a society TriggerEvent("esx_society:getSociety", xPlayer.job.name, function(society) - if society ~= nil then -- verified society + if society ~= nil then -- verified society TriggerEvent("esx_addonaccount:getSharedAccount", society.account, function(account) if account.money >= salary then -- does the society money to pay its employees? xPlayer.addAccountMoney("bank", salary, "Paycheck") account.removeMoney(salary) if Config.LogPaycheck then ESX.DiscordLogFields("Paycheck", "Paycheck - " .. jobLabel, "green", { - { name = "Player", value = xPlayer.name, inline = true }, - { name = "ID", value = xPlayer.source, inline = true }, - { name = "Amount", value = salary, inline = true }, + { name = "Player", value = xPlayer.name, inline = true }, + { name = "ID", value = xPlayer.source, inline = true }, + { name = "Amount", value = salary, inline = true }, }) end @@ -44,9 +45,9 @@ function StartPayCheck() xPlayer.addAccountMoney("bank", salary, "Paycheck") if Config.LogPaycheck then ESX.DiscordLogFields("Paycheck", "Paycheck - " .. jobLabel, "green", { - { name = "Player", value = xPlayer.name, inline = true }, - { name = "ID", value = xPlayer.source, inline = true }, - { name = "Amount", value = salary, inline = true }, + { name = "Player", value = xPlayer.name, inline = true }, + { name = "ID", value = xPlayer.source, inline = true }, + { name = "Amount", value = salary, inline = true }, }) end TriggerClientEvent("esx:showAdvancedNotification", player, TranslateCap("bank"), TranslateCap("received_paycheck"), TranslateCap("received_salary", salary), "CHAR_BANK_MAZE", 9) @@ -56,9 +57,9 @@ function StartPayCheck() xPlayer.addAccountMoney("bank", salary, "Paycheck") if Config.LogPaycheck then ESX.DiscordLogFields("Paycheck", "Paycheck - Generic", "green", { - { name = "Player", value = xPlayer.name, inline = true }, - { name = "ID", value = xPlayer.source, inline = true }, - { name = "Amount", value = salary, inline = true }, + { name = "Player", value = xPlayer.name, inline = true }, + { name = "ID", value = xPlayer.source, inline = true }, + { name = "Amount", value = salary, inline = true }, }) end TriggerClientEvent("esx:showAdvancedNotification", player, TranslateCap("bank"), TranslateCap("received_paycheck"), TranslateCap("received_salary", salary), "CHAR_BANK_MAZE", 9) From 9f0bafef3d607f6e3c87e79bc35d03bc394daf97 Mon Sep 17 00:00:00 2001 From: Mirow Date: Fri, 4 Apr 2025 17:02:10 +0200 Subject: [PATCH 3/3] Revert "feat(paycheck): add event" This reverts commit aba21e2c036caa770cf81fb8e19745f1691253a6. --- .../es_extended/server/modules/paycheck.lua | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/[core]/es_extended/server/modules/paycheck.lua b/[core]/es_extended/server/modules/paycheck.lua index cb7de3a9..54881709 100644 --- a/[core]/es_extended/server/modules/paycheck.lua +++ b/[core]/es_extended/server/modules/paycheck.lua @@ -9,30 +9,29 @@ function StartPayCheck() local salary = (job == "unemployed" or onDuty) and xPlayer.job.grade_salary or ESX.Math.Round(xPlayer.job.grade_salary * Config.OffDutyPaycheckMultiplier) if xPlayer.paycheckEnabled then - TriggerEvent("esx:paycheckReceived", xPlayer.source, salary, job, jobLabel, onDuty) if salary > 0 then if job == "unemployed" then -- unemployed xPlayer.addAccountMoney("bank", salary, "Welfare Check") TriggerClientEvent("esx:showAdvancedNotification", player, TranslateCap("bank"), TranslateCap("received_paycheck"), TranslateCap("received_help", salary), "CHAR_BANK_MAZE", 9) if Config.LogPaycheck then ESX.DiscordLogFields("Paycheck", "Paycheck - Unemployment Benefits", "green", { - { name = "Player", value = xPlayer.name, inline = true }, - { name = "ID", value = xPlayer.source, inline = true }, - { name = "Amount", value = salary, inline = true }, + { name = "Player", value = xPlayer.name, inline = true }, + { name = "ID", value = xPlayer.source, inline = true }, + { name = "Amount", value = salary, inline = true }, }) end - elseif Config.EnableSocietyPayouts then -- possibly a society + elseif Config.EnableSocietyPayouts then -- possibly a society TriggerEvent("esx_society:getSociety", xPlayer.job.name, function(society) - if society ~= nil then -- verified society + if society ~= nil then -- verified society TriggerEvent("esx_addonaccount:getSharedAccount", society.account, function(account) if account.money >= salary then -- does the society money to pay its employees? xPlayer.addAccountMoney("bank", salary, "Paycheck") account.removeMoney(salary) if Config.LogPaycheck then ESX.DiscordLogFields("Paycheck", "Paycheck - " .. jobLabel, "green", { - { name = "Player", value = xPlayer.name, inline = true }, - { name = "ID", value = xPlayer.source, inline = true }, - { name = "Amount", value = salary, inline = true }, + { name = "Player", value = xPlayer.name, inline = true }, + { name = "ID", value = xPlayer.source, inline = true }, + { name = "Amount", value = salary, inline = true }, }) end @@ -45,9 +44,9 @@ function StartPayCheck() xPlayer.addAccountMoney("bank", salary, "Paycheck") if Config.LogPaycheck then ESX.DiscordLogFields("Paycheck", "Paycheck - " .. jobLabel, "green", { - { name = "Player", value = xPlayer.name, inline = true }, - { name = "ID", value = xPlayer.source, inline = true }, - { name = "Amount", value = salary, inline = true }, + { name = "Player", value = xPlayer.name, inline = true }, + { name = "ID", value = xPlayer.source, inline = true }, + { name = "Amount", value = salary, inline = true }, }) end TriggerClientEvent("esx:showAdvancedNotification", player, TranslateCap("bank"), TranslateCap("received_paycheck"), TranslateCap("received_salary", salary), "CHAR_BANK_MAZE", 9) @@ -57,9 +56,9 @@ function StartPayCheck() xPlayer.addAccountMoney("bank", salary, "Paycheck") if Config.LogPaycheck then ESX.DiscordLogFields("Paycheck", "Paycheck - Generic", "green", { - { name = "Player", value = xPlayer.name, inline = true }, - { name = "ID", value = xPlayer.source, inline = true }, - { name = "Amount", value = salary, inline = true }, + { name = "Player", value = xPlayer.name, inline = true }, + { name = "ID", value = xPlayer.source, inline = true }, + { name = "Amount", value = salary, inline = true }, }) end TriggerClientEvent("esx:showAdvancedNotification", player, TranslateCap("bank"), TranslateCap("received_paycheck"), TranslateCap("received_salary", salary), "CHAR_BANK_MAZE", 9)