diff --git a/esx_example/README.md b/esx_example/README.md index 5f1baa98..36020956 100644 --- a/esx_example/README.md +++ b/esx_example/README.md @@ -1,4 +1,51 @@ -# fxserver-esx_boilerplate -FXServer ESX Boilerplate +### ESX Imports +##### Similar to importing the ESX locale functions or MySQL-Async, there is now an import for ESX +- Define `shared_script '@es_extended/imports.lua'` above all other scripts in your fxmanifest +- This will define the ESX object for both the client and server +##### The following event handler will also be created on the client +```lua + AddEventHandler('esx:setPlayerData', function(key, val) + if GetInvokingResource() == 'es_extended' then + ESX.PlayerData[key] = val + if OnPlayerData ~= nil then OnPlayerData(key, val) end + end + end) + ``` +- You will now receive updated ESX.PlayerData values whenever they change + - This does not include inventory or loadout data and it should still be retrieved with `ESX.GetPlayerData()` + - You can add your own functions to the import if you believe they will be useful in your resources + - You can trigger certain events or functions based on the key and value received (example in client.lua) + - The idea of this function is ensuring up-to-date values for `job, accounts, ped, and dead` + - You can set any data this way if you want to share it between resources + - Using `ESX.SetPlayerData('cuffed', true)` will create and set a new value that you can now reference anywhere + - If you are using OneSync you could set certain values to set a state bag (useful for other players to reference) -This a sample script for es_extended + +### Replacement for ESX.GetPlayers() +##### Old resources would utilise the ESX.GetPlayers() function in a loop with ESX.GetPlayerFromId() to retrieve xPlayer data +- This can be referred to as an xPlayer loop, and has been the cause for server hitches in resources such as esx_society and esx_status +- It is commonly used in robbery scripts to get the active number of cops, or for determining the number of EMS in other places +##### This method is outdated and should be replaced if you are using ESX Legacy +```lua + local xPlayers = ESX.GetPlayers() + for i=1, #xPlayers, 1 do + local xPlayer = ESX.GetPlayerFromId(xPlayers[i]) + if xPlayer.job.name == 'police' then + TriggerClientEvent('esx:showNotification', xPlayers[i], 'You are a cop!') + end + end +``` +##### This new method retrieves all xPlayer data at once, reducing the number of function references being called +```lua + local xPlayers = ESX.GetExtendedPlayers() -- Returns all xPlayers + for _, xPlayer in pairs(xPlayers) do + if v.job.name == 'police' then + TriggerClientEvent('esx:showNotification', xPlayer.source, 'You are a cop!') + end + end + + local xPlayers = ESX.GetExtendedPlayers('job', 'police') -- Returns xPlayers with the police job + for _, xPlayer in pairs(xPlayers) do + TriggerClientEvent('esx:showNotification', xPlayer.source, 'You are a cop!') + end +``` \ No newline at end of file diff --git a/esx_example/client/main.lua b/esx_example/client/main.lua index 880a0fec..818cc3d1 100644 --- a/esx_example/client/main.lua +++ b/esx_example/client/main.lua @@ -10,8 +10,6 @@ AddEventHandler('esx:playerLogout', function(xPlayer, isNew) ESX.PlayerData = {} end) - - -- These two functions can perform the same task RegisterNetEvent('esx:setJob') AddEventHandler('esx:setJob', function(job) @@ -40,4 +38,34 @@ OnPlayerData = function(key, val, last) end end end ------------------------------------------------ \ No newline at end of file +----------------------------------------------- + +RegisterCommand('closestobject', function() + local result = ESX.Game.GetClosestObject(GetEntityCoords(PlayerPedId())) + print(result) +end) + +RegisterCommand('closestped', function() + local result = ESX.Game.GetClosestPed(GetEntityCoords(PlayerPedId())) + print(result) +end) + +RegisterCommand('closestplayer', function() + local result = ESX.Game.GetClosestPlayer(GetEntityCoords(PlayerPedId())) + print(result) +end) + +RegisterCommand('closestvehicle', function() + local result = ESX.Game.GetClosestVehicle(GetEntityCoords(PlayerPedId())) + print(result) +end) + +RegisterCommand('areaplayer', function() + local result = ESX.Game.GetPlayersInArea(GetEntityCoords(PlayerPedId()), 20) + print(json.encode(result)) +end) + +RegisterCommand('areavehicle', function() + local result = ESX.Game.GetVehiclesInArea(GetEntityCoords(PlayerPedId()), 20) + print(json.encode(result)) +end) diff --git a/esx_example/server/main.lua b/esx_example/server/main.lua index 6ee5dcdf..970099eb 100644 --- a/esx_example/server/main.lua +++ b/esx_example/server/main.lua @@ -1,3 +1,8 @@ +Citizen.CreateThread(function() + Citizen.Wait(3000) + print('^1Do not run this resource in a live environment, it is solely intended for showcasing ESX functions^0') +end) + RegisterNetEvent('esx:playerLoaded') -- When a player loads in, we can store some basic information about them locally AddEventHandler('esx:playerLoaded', function(playerId, xPlayer, isNew) ESX.Players[playerId] = xPlayer.job.name @@ -16,17 +21,19 @@ AddEventHandler('onResourceStart', function(resourceName) -- The resource just r if (GetCurrentResourceName() == resourceName) then -- Useful if we need to run functions or send events after a restart local players = {} for _, xPlayer in pairs(ESX.Players) do - players[playerId] = xPlayer.job.name - print( ('%s %s is online with player id %s'):format(xPlayer.job.grade_label, xPlayer.name, playerId) ) + players[xPlayer.source] = xPlayer.job.name + print( ('%s %s is online with player id %s'):format(xPlayer.job.grade_label, xPlayer.name, xPlayer.source) ) end ESX.Players = players -- Replace the data as it is a waste of memory end end) -Citizen.CreateThread(function() - Citizen.Wait(1000) - local xPlayers = ESX.GetExtendedPlayers('job', 'police') -- New hitchless xPlayer loop, with the ability to only return players with specific data - for _, xPlayer in pairs(xPlayers) do +ESX.RegisterCommand('get', 'user', function(xPlayer, args, showError) + local xPlayers = ESX.GetExtendedPlayers(args.key, args.val) -- New hitchless xPlayer loop, with the ability to only return players with specific data + for _, xPlayer in pairs(xPlayers) do -- Job and any non-table variable will work, ie. name, group, identifier, source print(xPlayer.source, xPlayer.job.grade_label, xPlayer.name) end -end) \ No newline at end of file +end, true, {help = 'Display all online players with specific player data', validate = false, arguments = { + {name = 'key', help = 'Variable to check (ie. job)', type = 'string'}, + {name = 'val', help = 'Value required (ie. police)', type = 'any'} +}})