mirror of
https://github.com/esx-framework/esx_core.git
synced 2026-08-29 01:08:54 +00:00
refactor(esx_lib): move the player-state cache into the lib
Adds a generic xLib.cache (ped, vehicle, seat, weapon, coords) modelled on ox_lib cache and framework agnostic, and rewires es_extended to source ped and weapon from it which removes the per-frame ped poll. The vehicle enter/exit state machine and every esx: event are kept unchanged through a thin glue.
This commit is contained in:
@@ -1,10 +1,14 @@
|
||||
-- ESX glue over the generic xLib.cache.
|
||||
-- ped and weapon are tracked by the lib cache; this module mirrors them into
|
||||
-- ESX.PlayerData, re-emits the legacy esx: events resources depend on, and keeps
|
||||
-- the vehicle enter/exit state machine that produces the richer vehicle events.
|
||||
|
||||
Actions = {}
|
||||
Actions._index = Actions
|
||||
|
||||
Actions.inVehicle = false
|
||||
Actions.enteringVehicle = false
|
||||
Actions.inPauseMenu = false
|
||||
Actions.currentWeapon = false
|
||||
|
||||
function Actions:GetSeatPedIsIn()
|
||||
for i = -1, 16 do
|
||||
@@ -55,21 +59,6 @@ function Actions:TrackPedCoordsOnce()
|
||||
end)
|
||||
end
|
||||
|
||||
function Actions:TrackPed()
|
||||
local playerPed = ESX.PlayerData.ped
|
||||
local newPed = PlayerPedId()
|
||||
|
||||
if playerPed ~= newPed then
|
||||
ESX.SetPlayerData("ped", newPed)
|
||||
|
||||
TriggerEvent("esx:playerPedChanged", newPed)
|
||||
|
||||
if Config.EnableDebug then
|
||||
print("[DEBUG] Player ped changed:", newPed)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Actions:TrackPauseMenu()
|
||||
local isActive = IsPauseMenuActive()
|
||||
|
||||
@@ -189,46 +178,43 @@ function Actions:TrackSeat()
|
||||
end
|
||||
end
|
||||
|
||||
function Actions:TrackWeapon()
|
||||
---@type number|false
|
||||
local newWeapon = GetSelectedPedWeapon(ESX.PlayerData.ped)
|
||||
newWeapon = newWeapon ~= `WEAPON_UNARMED` and newWeapon or false
|
||||
|
||||
if newWeapon ~= self.currentWeapon then
|
||||
self.currentWeapon = newWeapon
|
||||
ESX.SetPlayerData("weapon", self.currentWeapon)
|
||||
TriggerEvent("esx:weaponChanged", self.currentWeapon)
|
||||
|
||||
if Config.EnableDebug then
|
||||
print("[DEBUG] Weapon changed:", self.currentWeapon)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function Actions:SlowLoop()
|
||||
CreateThread(function()
|
||||
while ESX.PlayerLoaded do
|
||||
self:TrackPauseMenu()
|
||||
self:TrackVehicle()
|
||||
self:TrackWeapon()
|
||||
Wait(500)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function Actions:PedLoop()
|
||||
CreateThread(function()
|
||||
while ESX.PlayerLoaded do
|
||||
self:TrackPed()
|
||||
Wait(0)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function Actions:Init()
|
||||
-- Re-seed the cached values on every (re)login. The change handlers below are
|
||||
-- registered once at file load so a relogin never stacks duplicate handlers.
|
||||
ESX.SetPlayerData("ped", xLib.cache.ped)
|
||||
ESX.SetPlayerData("weapon", xLib.cache.weapon)
|
||||
|
||||
self:SlowLoop()
|
||||
self:PedLoop()
|
||||
self:TrackPedCoordsOnce()
|
||||
end
|
||||
|
||||
-- Mirror the lib cache into ESX.PlayerData and re-emit the legacy esx: events.
|
||||
AddEventHandler("xLib:cache:ped", function(ped)
|
||||
ESX.SetPlayerData("ped", ped)
|
||||
TriggerEvent("esx:playerPedChanged", ped)
|
||||
|
||||
if Config.EnableDebug then
|
||||
print("[DEBUG] Player ped changed:", ped)
|
||||
end
|
||||
end)
|
||||
|
||||
AddEventHandler("xLib:cache:weapon", function(weapon)
|
||||
ESX.SetPlayerData("weapon", weapon)
|
||||
TriggerEvent("esx:weaponChanged", weapon)
|
||||
|
||||
if Config.EnableDebug then
|
||||
print("[DEBUG] Weapon changed:", weapon)
|
||||
end
|
||||
end)
|
||||
|
||||
Actions:Init()
|
||||
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
--[[
|
||||
Generic client-side player state cache, modelled on ox_lib cache.
|
||||
Framework agnostic: natives only, no ESX coupling.
|
||||
|
||||
Loaded per-resource VM through the lazy loader. PlayerPedId() and friends
|
||||
return the same value in every client VM, so the cached values are correct
|
||||
in each resource that requires it.
|
||||
|
||||
Exposes the live values as xLib.cache and emits `xLib:cache:<key>` (value, previous)
|
||||
whenever a tracked value changes. `coords` is read on demand from the live ped
|
||||
and never stored.
|
||||
]]
|
||||
|
||||
local playerId = PlayerId()
|
||||
|
||||
local cache = setmetatable({
|
||||
playerId = playerId,
|
||||
ped = PlayerPedId(),
|
||||
vehicle = false,
|
||||
seat = false,
|
||||
weapon = false,
|
||||
}, {
|
||||
__index = function(self, key)
|
||||
if key == "coords" then
|
||||
return GetEntityCoords(self.ped)
|
||||
elseif key == "serverId" then
|
||||
-- resolved lazily: GetPlayerServerId can return -1 before the network
|
||||
-- session is ready, so only cache it once it is valid.
|
||||
local id = GetPlayerServerId(playerId)
|
||||
if id and id ~= -1 then
|
||||
rawset(self, "serverId", id)
|
||||
end
|
||||
return id
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
local function set(key, value)
|
||||
if cache[key] == value then
|
||||
return
|
||||
end
|
||||
|
||||
local previous = cache[key]
|
||||
rawset(cache, key, value)
|
||||
TriggerEvent(("xLib:cache:%s"):format(key), value, previous)
|
||||
end
|
||||
|
||||
local function getSeat(ped, vehicle)
|
||||
for seat = -1, 16 do
|
||||
if GetPedInVehicleSeat(vehicle, seat) == ped then
|
||||
return seat
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
CreateThread(function()
|
||||
while true do
|
||||
local ped = PlayerPedId()
|
||||
if ped ~= cache.ped then
|
||||
set("ped", ped)
|
||||
end
|
||||
|
||||
---@type integer|false
|
||||
local vehicle = GetVehiclePedIsIn(ped, false)
|
||||
vehicle = vehicle ~= 0 and vehicle or false
|
||||
|
||||
if vehicle ~= cache.vehicle then
|
||||
set("vehicle", vehicle)
|
||||
set("seat", vehicle and getSeat(ped, vehicle) or false)
|
||||
elseif vehicle then
|
||||
local seat = getSeat(ped, vehicle)
|
||||
if seat ~= cache.seat then
|
||||
set("seat", seat)
|
||||
end
|
||||
end
|
||||
|
||||
---@type integer|false
|
||||
local weapon = GetSelectedPedWeapon(ped)
|
||||
weapon = weapon ~= `WEAPON_UNARMED` and weapon or false
|
||||
if weapon ~= cache.weapon then
|
||||
set("weapon", weapon)
|
||||
end
|
||||
|
||||
Wait(100)
|
||||
end
|
||||
end)
|
||||
|
||||
return cache
|
||||
Reference in New Issue
Block a user