diff --git a/[core]/es_extended/client/main.lua b/[core]/es_extended/client/main.lua index 0c851b5f..129b800f 100644 --- a/[core]/es_extended/client/main.lua +++ b/[core]/es_extended/client/main.lua @@ -522,82 +522,82 @@ AddEventHandler("esx:tpm", function() local GetBlipInfoIdCoord = GetBlipInfoIdCoord local GetVehiclePedIsIn = GetVehiclePedIsIn - ESX.TriggerServerCallback("esx:isUserAdmin", function(admin) - if not admin then - return - end - local blipMarker = GetFirstBlipInfoId(8) - if not DoesBlipExist(blipMarker) then - ESX.ShowNotification(TranslateCap('tpm_nowaypoint'), true, false, 140) - return 'marker' + local admin = ESX.TriggerServerCallback.Await("esx:isUserAdmin") + if not admin then + return + end + + local blipMarker = GetFirstBlipInfoId(8) + if not DoesBlipExist(blipMarker) then + ESX.ShowNotification(TranslateCap('tpm_nowaypoint'), true, false, 140) + return 'marker' + end + + -- Fade screen to hide how clients get teleported. + DoScreenFadeOut(650) + while not IsScreenFadedOut() do + Wait(0) + end + + local ped, coords = ESX.PlayerData.ped, GetBlipInfoIdCoord(blipMarker) + local vehicle = GetVehiclePedIsIn(ped, false) + local oldCoords = GetEntityCoords(ped) + + -- Unpack coords instead of having to unpack them while iterating. + -- 825.0 seems to be the max a player can reach while 0.0 being the lowest. + local x, y, groundZ, Z_START = coords['x'], coords['y'], 850.0, 950.0 + local found = false + FreezeEntityPosition(vehicle > 0 and vehicle or ped, true) + + for i = Z_START, 0, -25.0 do + local z = i + if (i % 2) ~= 0 then + z = Z_START - i end - -- Fade screen to hide how clients get teleported. - DoScreenFadeOut(650) - while not IsScreenFadedOut() do + NewLoadSceneStart(x, y, z, x, y, z, 50.0, 0) + local curTime = GetGameTimer() + while IsNetworkLoadingScene() do + if GetGameTimer() - curTime > 1000 then + break + end Wait(0) end + NewLoadSceneStop() + SetPedCoordsKeepVehicle(ped, x, y, z) - local ped, coords = ESX.PlayerData.ped, GetBlipInfoIdCoord(blipMarker) - local vehicle = GetVehiclePedIsIn(ped, false) - local oldCoords = GetEntityCoords(ped) - - -- Unpack coords instead of having to unpack them while iterating. - -- 825.0 seems to be the max a player can reach while 0.0 being the lowest. - local x, y, groundZ, Z_START = coords['x'], coords['y'], 850.0, 950.0 - local found = false - FreezeEntityPosition(vehicle > 0 and vehicle or ped, true) - - for i = Z_START, 0, -25.0 do - local z = i - if (i % 2) ~= 0 then - z = Z_START - i - end - - NewLoadSceneStart(x, y, z, x, y, z, 50.0, 0) - local curTime = GetGameTimer() - while IsNetworkLoadingScene() do - if GetGameTimer() - curTime > 1000 then - break - end - Wait(0) - end - NewLoadSceneStop() - SetPedCoordsKeepVehicle(ped, x, y, z) - - while not HasCollisionLoadedAroundEntity(ped) do - RequestCollisionAtCoord(x, y, z) - if GetGameTimer() - curTime > 1000 then - break - end - Wait(0) - end - - -- Get ground coord. As mentioned in the natives, this only works if the client is in render distance. - found, groundZ = GetGroundZFor_3dCoord(x, y, z, false) - if found then - Wait(0) - SetPedCoordsKeepVehicle(ped, x, y, groundZ) + while not HasCollisionLoadedAroundEntity(ped) do + RequestCollisionAtCoord(x, y, z) + if GetGameTimer() - curTime > 1000 then break end Wait(0) end - -- Remove black screen once the loop has ended. - DoScreenFadeIn(650) - FreezeEntityPosition(vehicle > 0 and vehicle or ped, false) - - if not found then - -- If we can't find the coords, set the coords to the old ones. - -- We don't unpack them before since they aren't in a loop and only called once. - SetPedCoordsKeepVehicle(ped, oldCoords['x'], oldCoords['y'], oldCoords['z'] - 1.0) - ESX.ShowNotification(TranslateCap('tpm_success'), true, false, 140) + -- Get ground coord. As mentioned in the natives, this only works if the client is in render distance. + found, groundZ = GetGroundZFor_3dCoord(x, y, z, false) + if found then + Wait(0) + SetPedCoordsKeepVehicle(ped, x, y, groundZ) + break end + Wait(0) + end - -- If Z coord was found, set coords in found coords. - SetPedCoordsKeepVehicle(ped, x, y, groundZ) + -- Remove black screen once the loop has ended. + DoScreenFadeIn(650) + FreezeEntityPosition(vehicle > 0 and vehicle or ped, false) + + if not found then + -- If we can't find the coords, set the coords to the old ones. + -- We don't unpack them before since they aren't in a loop and only called once. + SetPedCoordsKeepVehicle(ped, oldCoords['x'], oldCoords['y'], oldCoords['z'] - 1.0) ESX.ShowNotification(TranslateCap('tpm_success'), true, false, 140) - end) + end + + -- If Z coord was found, set coords in found coords. + SetPedCoordsKeepVehicle(ped, x, y, groundZ) + ESX.ShowNotification(TranslateCap('tpm_success'), true, false, 140) end) local noclip = false @@ -646,24 +646,23 @@ local function noclipThread() end RegisterNetEvent("esx:noclip") -AddEventHandler("esx:noclip", function(input) - ESX.TriggerServerCallback("esx:isUserAdmin", function(admin) - if not admin then - return - end +AddEventHandler("esx:noclip", function() + local admin = ESX.TriggerServerCallback.Await("esx:isUserAdmin") + if not admin then + return + end - if not noclip then - noclip_pos = GetEntityCoords(ESX.PlayerData.ped, false) - heading = GetEntityHeading(ESX.PlayerData.ped) - end + if not noclip then + noclip_pos = GetEntityCoords(ESX.PlayerData.ped, false) + heading = GetEntityHeading(ESX.PlayerData.ped) + end - noclip = not noclip - if noclip then - CreateThread(noclipThread) - end + noclip = not noclip + if noclip then + CreateThread(noclipThread) + end - ESX.ShowNotification(TranslateCap('noclip_message', noclip and "enabled" or "disabled"), true, false, 140) - end) + ESX.ShowNotification(TranslateCap('noclip_message', noclip and "enabled" or "disabled"), true, false, 140) end) RegisterNetEvent("esx:killPlayer") diff --git a/[core]/es_extended/client/modules/callback.lua b/[core]/es_extended/client/modules/callback.lua index 180c9216..a4d03d3b 100644 --- a/[core]/es_extended/client/modules/callback.lua +++ b/[core]/es_extended/client/modules/callback.lua @@ -3,22 +3,47 @@ local serverRequests = {} local clientCallbacks = {} ----@param eventName string ----@param callback function ----@param ... any -ESX.TriggerServerCallback = function(eventName, callback, ...) - serverRequests[RequestId] = callback - - TriggerServerEvent('esx:triggerServerCallback', eventName, RequestId, GetInvokingResource() or "unknown", ...) +ESX.TriggerServerCallback = setmetatable({ + ---@param eventName string + ---@param ... any + Await = function(eventName, ...) + assert(type(eventName) == 'string', 'Argument 1 `eventName` is not a string!') + local p = promise.new() - RequestId = RequestId + 1 -end + serverRequests[RequestId] = p + + TriggerServerEvent('esx:triggerServerCallback', eventName, RequestId, GetInvokingResource() or "unknown", ...) + + RequestId = RequestId + 1 + + return Citizen.Await(p) + end +}, { + ---@param eventName string + ---@param callback function + ---@param ... any + __call = function(_, eventName, callback, ...) + assert(type(eventName) == 'string', 'Argument 1 `eventName` is not a string!') + assert(type(callback) == 'function', 'Argument 2 `callback` is not a function!') + + serverRequests[RequestId] = callback + + TriggerServerEvent('esx:triggerServerCallback', eventName, RequestId, GetInvokingResource() or "unknown", ...) + + RequestId = RequestId + 1 + end +}) RegisterNetEvent('esx:serverCallback', function(requestId, invoker, ...) if not serverRequests[requestId] then return print(('[^1ERROR^7] Server Callback with requestId ^5%s^7 Was Called by ^5%s^7 but does not exist.'):format(requestId, invoker)) end + if type(serverRequests[requestId]) == 'table' then + serverRequests[requestId]:resolve(...) + return + end + serverRequests[requestId](...) serverRequests[requestId] = nil end) diff --git a/[core]/es_extended/server/modules/callback.lua b/[core]/es_extended/server/modules/callback.lua index 4c7e17fd..9d78696b 100644 --- a/[core]/es_extended/server/modules/callback.lua +++ b/[core]/es_extended/server/modules/callback.lua @@ -21,23 +21,56 @@ RegisterNetEvent('esx:triggerServerCallback', function(eventName, requestId, inv end, ...) end) ----@param player number playerId ----@param eventName string ----@param callback function ----@param ... any -ESX.TriggerClientCallback = function(player, eventName, callback, ...) - clientRequests[RequestId] = callback +ESX.TriggerClientCallback = setmetatable({ + ---@param player number? + ---@param eventName string + ---@param ... any + Await = function(player, eventName, ...) + player = tonumber(player) - TriggerClientEvent('esx:triggerClientCallback', player, eventName, RequestId, GetInvokingResource() or "unknown", ...) + assert(player, 'Argument 1 `player` is not a number!') + assert(type(eventName) == 'string', 'Argument 2 `eventName` is not a string!') - RequestId = RequestId + 1 -end + local p = promise.new() + + clientRequests[RequestId] = p + + TriggerClientEvent('esx:triggerClientCallback', player, eventName, RequestId, GetInvokingResource() or "unknown", ...) + + RequestId = RequestId + 1 + + return Citizen.Await(p) + end +}, { + ---@param player number? playerId + ---@param eventName string + ---@param callback function + ---@param ... any + __call = function(_, player, eventName, callback, ...) + player = tonumber(player) + + assert(player, 'Argument 1 `player` is not a number!') + assert(type(eventName) == 'string', 'Argument 2 `eventName` is not a string!') + assert(type(callback) == 'function', 'Argument 3 `callback` is not a function!') + + clientRequests[RequestId] = callback + + TriggerClientEvent('esx:triggerClientCallback', player, eventName, RequestId, GetInvokingResource() or "unknown", ...) + + RequestId = RequestId + 1 + end +}) RegisterNetEvent('esx:clientCallback', function(requestId, invoker, ...) if not clientRequests[requestId] then return print(('[^1ERROR^7] Client Callback with requestId ^5%s^7 Was Called by ^5%s^7 but does not exist.'):format(requestId, invoker)) end + if type(clientRequests[requestId]) == 'table' then + clientRequests[requestId]:resolve(...) + return + end + clientRequests[requestId](...) clientRequests[requestId] = nil end) \ No newline at end of file