monitor/resource/menu/client/cl_base.lua
2025-04-16 22:30:27 +07:00

232 lines
7.4 KiB
Lua

-- =============================================
-- This file is for base menu functionality (admin status,
-- visibility, keybinds, focus callbacks's, threads, etc)
-- =============================================
-- Global Variables
-- TODO: they should be upper case
menuIsAccessible = false
isMenuVisible = false
tsLastMenuClose = 0
menuPermissions = {}
lastTpCoords = false;
-- Locals
local noMenuReason = 'unknown reason'
local awaitingReauth = false
--- Logic to displaying the menu auth rejected snackbar
local function displayAuthRejectedError()
if noMenuReason == 'nui_admin_not_found' then
sendSnackbarMessage('error', 'nui_menu.misc.menu_not_admin', true)
else
sendSnackbarMessage('error', 'nui_menu.misc.menu_auth_failed', true, { reason = noMenuReason })
end
end
--- Tests for menu accessibility and displays error snackbar if needed
local function checkMenuAccessible()
if not TX_MENU_ENABLED then
sendSnackbarMessage('error', 'nui_menu.misc.not_enabled', true)
return false
end
if not menuIsAccessible then
displayAuthRejectedError()
return false
end
return true
end
-- Register txAdmin command
local function txadmin(_, args)
if not checkMenuAccessible() then return end
-- Make visible
toggleMenuVisibility()
-- Shortcut to open a specific players profile
if isMenuVisible and #args >= 1 then
local targetPlayer = table.concat(args, ' ')
sendMenuMessage('openPlayerModal', targetPlayer)
end
end
RegisterCommand('txadmin', txadmin)
RegisterCommand('tx', txadmin)
RegisterCommand('txAdmin:menu:openPlayersPage', function()
if not checkMenuAccessible() then return end
sendMenuMessage('setMenuPage', 1)
toggleMenuVisibility(true)
SetNuiFocus(true, true)
end)
-- This needs to run even when menu is disabled so the ServerCtx
-- is updated for react, needed by the Warn page
RegisterSecureNuiCallback('reactLoaded', function(_, cb)
debugPrint("React loaded, requesting ServerCtx.")
CreateThread(function()
updateServerCtx()
while ServerCtx == false do Wait(0) end
debugPrint("ServerCtx loaded, sending variables.")
sendMenuMessage('setGameName', GAME_NAME)
sendMenuMessage('setDebugMode', TX_DEBUG_MODE)
sendMenuMessage('setServerCtx', ServerCtx)
sendMenuMessage('setPermissions', menuPermissions)
end)
cb({})
end)
-- =============================================
-- The rest of the file will only run if menu is enabled
-- =============================================
-- Prevent running if menu is disabled
if not TX_MENU_ENABLED then return end
-- Checking with server if we are an admin
TriggerServerEvent('txsv:checkIfAdmin')
-- Triggered as callback of txsv:checkIfAdmin
RegisterNetEvent('txcl:setAdmin', function(username, perms, rejectReason)
if type(perms) == 'table' then
debugPrint("^2[AUTH] logged in as '" .. username .. "' with perms: " .. json.encode(perms or "nil"))
menuIsAccessible = true
menuPermissions = perms
if IS_FIVEM then
--NOTE: appending # to the desc so the sorting shows it at the top
RegisterKeyMapping('txadmin', 'Open Main Page', 'KEYBOARD', '')
RegisterKeyMapping('txAdmin:menu:openPlayersPage', 'Open Players page', 'KEYBOARD', '')
RegisterKeyMapping('txAdmin:menu:clearArea', 'Clear Area', 'KEYBOARD', '')
RegisterKeyMapping('txAdmin:menu:healMyself', 'Heal Yourself', 'KEYBOARD', '')
RegisterKeyMapping('txAdmin:menu:tpBack', 'Teleport: go Back', 'KEYBOARD', '')
RegisterKeyMapping('txAdmin:menu:tpToCoords', 'Teleport: to Coords', 'KEYBOARD', '')
RegisterKeyMapping('txAdmin:menu:tpToWaypoint', 'Teleport: to Waypoint', 'KEYBOARD', '')
RegisterKeyMapping('txAdmin:menu:noClipToggle', 'Toggle NoClip', 'KEYBOARD', '')
RegisterKeyMapping('txAdmin:menu:togglePlayerIDs', 'Toggle Player IDs', 'KEYBOARD', '')
RegisterKeyMapping('txAdmin:menu:boostVehicle', 'Vehicle: Boost', 'KEYBOARD', '')
RegisterKeyMapping('txAdmin:menu:deleteVehicle', 'Vehicle: Delete', 'KEYBOARD', '')
RegisterKeyMapping('txAdmin:menu:fixVehicle', 'Vehicle: Fix', 'KEYBOARD', '')
RegisterKeyMapping('txAdmin:menu:spawnVehicle', 'Vehicle: Spawn', 'KEYBOARD', '')
end
else
noMenuReason = tostring(rejectReason)
debugPrint("^3[AUTH] rejected (" .. noMenuReason .. ")")
if awaitingReauth then
displayAuthRejectedError()
awaitingReauth = false
end
menuIsAccessible = false
menuPermissions = {}
end
sendMenuMessage('setPermissions', menuPermissions)
end)
--[[ Debug Events / Commands ]]
-- Command/event to trigger a authentication attempt
local function retryAuthentication()
debugPrint("^5[AUTH] Retrying menu authentication.")
menuIsAccessible = false
menuPermissions = {}
sendMenuMessage('setPermissions', menuPermissions)
TriggerServerEvent('txsv:checkIfAdmin')
end
RegisterNetEvent('txcl:reAuth', retryAuthentication)
RegisterCommand('txAdmin-reauth', function()
sendSnackbarMessage('info', 'Retrying menu authentication.', false)
awaitingReauth = true
retryAuthentication()
end)
-- Register chat suggestions
-- txAdmin starts before the chat resource, so we need to wait a bit
CreateThread(function()
Wait(1000)
TriggerEvent(
'chat:addSuggestion',
'/tx',
'Opens the main txAdmin Menu or specific for a player.',
{ { name = "player ID/name", help = "(Optional) Open player modal for specific ID or name." } }
)
TriggerEvent(
'chat:addSuggestion',
'/txAdmin-reauth',
'Retries to authenticate the menu NUI.'
)
end)
-- Will toggle debug logging
RegisterNetEvent('txcl:setDebugMode', function(enabled)
TX_DEBUG_MODE = enabled
sendMenuMessage('setDebugMode', TX_DEBUG_MODE)
end)
--[[ NUI Callbacks ]]
-- Triggered whenever we require full focus, cursor and keyboard
RegisterSecureNuiCallback('focusInputs', function(shouldFocus, cb)
debugPrint('NUI Focus + Keep Input ' .. tostring(shouldFocus))
-- Will prevent mouse focus on initial menu mount as the useEffect emits there
if not isMenuVisible then
return
end
SetNuiFocus(true, shouldFocus)
SetNuiFocusKeepInput(not shouldFocus)
cb({})
end)
-- When the escape key is pressed in menu
RegisterSecureNuiCallback('closeMenu', function(_, cb)
isMenuVisible = false
tsLastMenuClose = GetGameTimer()
debugPrint('Releasing all NUI Focus')
SetNuiFocus(false)
SetNuiFocusKeepInput(false)
playLibrarySound('enter')
cb({})
end)
-- Audio play callback
RegisterSecureNuiCallback('playSound', function(sound, cb)
playLibrarySound(sound)
cb({})
end)
-- Heals local player
RegisterNetEvent('txcl:heal', function()
debugPrint('Received heal event, healing to full')
local ped = PlayerPedId()
local pos = GetEntityCoords(ped)
local heading = GetEntityHeading(ped)
if IsEntityDead(ped) then
NetworkResurrectLocalPlayer(pos[1], pos[2], pos[3], heading, false, false)
end
ResurrectPed(ped)
SetEntityHealth(ped, GetEntityMaxHealth(ped))
ClearPedBloodDamage(ped)
RestorePlayerStamina(PlayerId(), 100.0)
if IS_REDM then
Citizen.InvokeNative(0xC6258F41D86676E0, ped, 0, 100) -- SetAttributeCoreValue
Citizen.InvokeNative(0xC6258F41D86676E0, ped, 1, 100) -- SetAttributeCoreValue
Citizen.InvokeNative(0xC6258F41D86676E0, ped, 2, 100) -- SetAttributeCoreValue
end
end)
-- Tell the user he is an admin and that /tx is available
AddEventHandler('playerSpawned', function()
Wait(15000)
if menuIsAccessible then
sendMenuMessage('showMenuHelpInfo', {})
end
end)