Discarded entityactions and updated target

Discarded entityactions: was not used and bloat. Need a new system that handled networked entities static vs dynamic (non-moving non networked vs moving networked)

updated target to improve performance on canInteract. It seems that the target systems spam this function. Using a state and checking every second instead of allowing spamming

Added ClientEntity.ChangeModel
This commit is contained in:
Mr.Crowley committed 2025-08-20 22:23:07 -05:00
1 parent cbd340326d
commit b06d2fb49e
8 files changed
+73 -190

No files matched your search

+14 -51
View File
@@ -1,7 +1,6 @@
Utility = Utility or Require("lib/utility/client/utility.lua")
Ids = Ids or Require("lib/utility/shared/ids.lua")
Point = Point or Require("lib/points/client/points.lua")
ClientEntityActions = ClientEntityActions or Require("lib/entities/client/client_entity_actions_ext.lua") -- Added
local Entities = {} -- Stores entity data received from server
ClientEntity = {} -- Renamed from BaseEntity
@@ -86,8 +85,6 @@ end
-- Depricated use ClientEntity.CreateBulk instead
ClientEntity.RegisterBulk = ClientEntity.CreateBulk
--- Unregisters an entity and removes it from the world if spawned.
-- @param id string|number The ID of the entity to unregister.
function ClientEntity.Destroy(id)
@@ -100,7 +97,6 @@ function ClientEntity.Destroy(id)
end
ClientEntity.Unregister = ClientEntity.Destroy
--- Updates the data for a registered entity.
-- @param id string|number The ID of the entity to update.
-- @param data table The data fields to update.
@@ -165,10 +161,6 @@ function ClientEntity.GetAll()
return Entities
end
function ClientEntity.RegisterAction(name, func)
ClientEntityActions.RegisterAction(name, func)
end
function ClientEntity.OnCreate(_type, func)
ClientEntity.OnCreates = ClientEntity.OnCreates or {}
if not ClientEntity.OnCreates[_type] then
@@ -203,11 +195,22 @@ function ClientEntity.UpdateCoords(id, coords)
end
entityData.coords = coords
Point.UpdateCoords(id, coords)
if entityData.spawned and DoesEntityExist(entityData.spawned) then
SetEntityCoords(entityData.spawned, coords.x, coords.y, coords.z, false, false, false, true)
end
if not entityData.spawned or not DoesEntityExist(entityData.spawned) then return end
SetEntityCoords(entityData.spawned, coords.x, coords.y, coords.z, false, false, false, true)
end
function ClientEntity.ChangeModel(id, model)
local entityData = Entities[id]
if not entityData then return print(string.format("[ClientEntity] ChangeModel: Entity %s does not exist", id)) end
entityData.model = model
if not entityData.spawned or not DoesEntityExist(entityData.spawned) then return end
RemoveEntity(entityData)
SpawnEntity(entityData)
end
-- Network Event Handlers
RegisterNetEvent("community_bridge:client:CreateEntity", function(entityData)
ClientEntity.Create(entityData)
@@ -225,46 +228,6 @@ RegisterNetEvent("community_bridge:client:UpdateEntity", function(id, data)
ClientEntity.Update(id, data)
end)
-- New handler for entity actions
RegisterNetEvent("community_bridge:client:TriggerEntityAction", function(entityId, actionName, ...)
local entityData = Entities[entityId]
-- Check if entity exists locally (it doesn't need to be spawned to queue actions)
if entityData then
if actionName == "Stop" then
ClientEntityActions.StopAction(entityId)
elseif actionName == "Skip" then
ClientEntityActions.SkipAction(entityId)
else
print(string.format("[ClientEntity] Triggering action '%s' for entity %s", actionName, entityId))
local currentAction = ClientEntityActions.ActionQueue[entityId] and ClientEntityActions.ActionQueue[entityId][1]
ClientEntityActions.QueueAction(entityData, actionName, ...)
end
-- else
-- Optional: Log if action received but entity doesn't exist locally at all
-- print(string.format("[ClientEntity] Received action '%s' for non-existent entity %s.", actionName, entityId))
end
end)
RegisterNetEvent("community_bridge:client:TriggerEntityActions", function(entityId, actions, endPosition)
local entityData = Entities[entityId]
if entityData then
for _, actionData in pairs(actions) do
local actionName = actionData.name
local actionParams = actionData.params
if actionName == "Stop" then
ClientEntityActions.StopAction(entityId)
elseif actionName == "Skip" then
ClientEntityActions.SkipAction(entityId)
else
local currentAction = ClientEntityActions.ActionQueue[entityId] and ClientEntityActions.ActionQueue[entityId][1]
ClientEntityActions.QueueAction(entityData, actionName, table.unpack(actionParams))
end
end
else
print(string.format("[ClientEntity] Received actions for non-existent entity %s.", entityId))
end
end)
-- Resource Stop Cleanup
AddEventHandler('onResourceStop', function(resourceName)
if resourceName == GetCurrentResourceName() then
@@ -1,136 +0,0 @@
ClientEntityActions = {}
ClientEntityActions.ActionThreads = {} -- Store running action threads { [entityId] = thread }
ClientEntityActions.ActionQueue = {} -- Stores pending actions { [entityId] = {{name="ActionName", args={...}}, ...} }
ClientEntityActions.IsActionRunning = {} -- Tracks if an action is currently running { [entityId] = boolean }
ClientEntityActions.RegisteredActions = {} -- New: Registry for action implementations { [actionName] = function(entityData, ...) }
-- Forward declaration
--- Processes the next action in the queue for a given entity.
-- @param entityId string|number The ID of the entity.
function ClientEntityActions.ProcessNextAction(entityId)
if ClientEntityActions.IsActionRunning [entityId] then return end -- Already running something
local queue = ClientEntityActions.ActionQueue[entityId]
if not queue or #queue == 0 then return end -- Queue is empty
local nextAction = table.remove(queue, 1) -- Dequeue (FIFO)
local entityData = ClientEntity.Get(entityId) -- Assumes ClientEntity is accessible
-- Check if entity is still valid and spawned before starting next action
if not entityData or not entityData.spawned or not DoesEntityExist(entityData.spawned) then
-- Entity despawned while idle, clear queue and do nothing
ClientEntityActions.ActionQueue[entityId] = nil
return
end
-- Look up the action in the registry
local actionFunc = ClientEntityActions.RegisteredActions [nextAction.name]
if actionFunc then
-- print(string.format("[ClientEntityActions] Starting action '%s' for entity %s", nextAction.name, entityId))
ClientEntityActions.IsActionRunning [entityId] = true
-- Call the registered function
ClientEntityActions.ActionQueue[entityId] = actionFunc(entityData, table.unpack(nextAction.args))
if not ClientEntityActions.ActionQueue[entityId] then
-- If the action function doesn't return a queue, set it to nil
ClientEntityActions.IsActionRunning[entityId] = false
ClientEntityActions.ProcessNextAction(entityId) -- Try next action if this one failed immediately
end
else
print(string.format("[ClientEntityActions] Unknown action '%s' dequeued for entity %s", nextAction.name, entityId))
-- Skip unknown action and try the next one immediately
ClientEntityActions.ActionQueue[entityId] = ClientEntityActions.ProcessNextAction(entityId)
end
end
--- Registers a custom action implementation.
-- The action function should handle its own logic, including threading if needed,
-- and MUST call ClientEntityActions.ProcessNextAction(entityData.id) when it completes or fails,
-- after setting ClientEntityActions.IsActionRunning [entityData.id] = false.
-- @param actionName string The name used to trigger this action.
-- @param actionFunc function The function to execute. Signature: function(entityData, ...)
function ClientEntityActions.RegisterAction(actionName, actionFunc)
if ClientEntityActions.RegisteredActions [actionName] then
print(string.format("[ClientEntityActions] WARNING: Overwriting registered action '%s'", actionName))
end
assert(type(actionName) == "string", "actionName must be a string")
ClientEntityActions.RegisteredActions[actionName] = actionFunc
-- print(string.format("[ClientEntityActions] Registered action: %s", actionName))
end
--- Queues an action for an entity. Starts processing if idle.
-- @param entityData table The entity data.
-- @param actionName string The name of the action.
-- @param ... any Arguments for the action.
function ClientEntityActions.QueueAction(entityData, actionName, ...)
local entityId = entityData.id
if not ClientEntityActions.ActionQueue[entityId] then
ClientEntityActions.ActionQueue[entityId] = {}
end
local actionArgs = {...}
table.insert(ClientEntityActions.ActionQueue[entityId], { name = actionName, args = actionArgs })
-- print(string.format("[ClientEntityActions] Queued action '%s' for entity %s. Queue size: %d", actionName, entityId, #ClientEntityActions.ActionQueue[entityId]))
-- If the entity isn't currently doing anything, start processing immediately
if not ClientEntityActions.IsActionRunning [entityId] then
ClientEntityActions.ProcessNextAction(entityId)
end
end
--- Stops the current action and clears the queue for a specific entity.
-- @param entityId string|number The ID of the entity.
function ClientEntityActions.StopAction(entityId)
-- print(string.format("[ClientEntityActions] Stopping all actions for entity %s", entityId))
ClientEntityActions.ActionQueue[entityId] = nil -- Clear the queue
ClientEntityActions.IsActionRunning [entityId] = false -- Mark as not running (this will stop loops in threads)
-- Stop current task/thread if applicable
if ClientEntityActions.ActionThreads[entityId] then
-- Lua threads stop themselves based on ClientEntityActions.IsActionRunning flag
ClientEntityActions.ActionThreads[entityId] = nil
end
-- Specific task clearing for peds
local entityData = ClientEntity.Get(entityId)
if entityData and entityData.spawned and DoesEntityExist(entityData.spawned) then
if IsEntityAPed(entityData.spawned) then
ClearPedTasksImmediately(entityData.spawned) -- Use Immediately for forceful stop
end
-- Other entity types might need different stop logic
end
end
--- Skips the current action and starts the next one in the queue, if any.
-- @param entityId string|number The ID of the entity.
function ClientEntityActions.SkipAction(entityId)
if not ClientEntityActions.IsActionRunning [entityId] then
-- print(string.format("[ClientEntityActions] SkipAction called for %s, but no action running.", entityId))
return -- Nothing to skip
end
-- print(string.format("[ClientEntityActions] Skipping current action for entity %s", entityId))
ClientEntityActions.IsActionRunning [entityId] = false -- Mark as not running (this will stop loops in threads)
-- Stop current task/thread if applicable
if ClientEntityActions.ActionThreads[entityId] then
ClientEntityActions.ActionThreads[entityId] = nil
end
local entityData = ClientEntity.Get(entityId)
if entityData and entityData.spawned and DoesEntityExist(entityData.spawned) then
if IsEntityAPed(entityData.spawned) then
ClearPedTasksImmediately(entityData.spawned)
end
end
-- Immediately try to process the next action
ClientEntityActions.ProcessNextAction(entityId)
end
-- Add server-callable functions for Stop and Skip
function ClientEntityActions.Stop(entityData)
ClientEntityActions.StopAction(entityData.id)
end
function ClientEntityActions.Skip(entityData)
ClientEntityActions.SkipAction(entityData.id)
end
return ClientEntityActions
-1
View File
@@ -29,7 +29,6 @@ end
function ServerEntity.Create(id, entityType, model, coords, rotation, meta)
local self = ServerEntity.New(id, entityType, model, coords, rotation, meta)
if not self then
-- print("Failed to create entity with ID: " .. tostring(id))
return nil
end
TriggerClientEvent("community_bridge:client:CreateEntity", -1, self)
-1
View File
@@ -76,7 +76,6 @@ cLib.Point = Point or Require("lib/points/client/pointsv2.lua")
cLib.Particle = Particle or Require("lib/particles/client/particles.lua")
cLib.Cache = Cache or Require("lib/cache/client/cache.lua")
cLib.ClientEntity = ClientEntity or Require("lib/entities/client/client_entity.lua")
cLib.ClientEntityActions = ClientEntityActions or Require("lib/entities/client/client_entity_actions.lua")
cLib.ClientStateBag = ClientStateBag or Require("lib/statebags/client/client.lua")
cLib.Marker = Marker or Require("lib/markers/client/markers.lua")
cLib.Anim = Anim or Require("lib/anim/client/client.lua")
+38 -1
View File
@@ -1,9 +1,40 @@
---@diagnostic disable: duplicate-set-field
Target = Target or {}
Ids = Ids or Require("lib/utility/shared/ids.lua")
local function warnUser()
print("Currently Only Targeting Is Supported By Community Bridge, You Are Using A Resource That Requires The Target Module To Be Used.")
end
local InteractIds = {}
Target.GetCanInteract = function(id)
return InteractIds[id]
end
Target.CreateCanInteract = function(cb)
if not cb then return end
local id = Ids.CreateUniqueId(InteractIds)
InteractIds[id] = {
id = id,
ableToInteract = -1,
onInteract = cb
}
return id
end
Target.CanInteract = function(id, ...)
local interactData = InteractIds[id]
if not interactData then return true end
if interactData.ableToInteract == -1 then
local cb = interactData.onInteract
local canInteractStatus = cb(...)
interactData.ableToInteract = canInteractStatus and 1 or 0
SetTimeout(1000, function()
interactData.ableToInteract = -1
end)
end
return interactData.ableToInteract > 0
end
Target.FixOptions = function(options)
for k, v in pairs(options) do
@@ -15,6 +46,13 @@ Target.FixOptions = function(options)
return action(entityOrData)
end
options[k].onSelect = select
local optionsCanInteract = v.canInteract
if optionsCanInteract then
local id = Target.CreateCanInteract(optionsCanInteract)
v.canInteract = function(...)
return Target.CanInteract(id, ...)
end
end
end
return options
end
@@ -78,7 +116,6 @@ Target.AddLocalEntity = function(entities, _options)
end
end
Target.AddModel = function(models, options)
warnUser()
end
+7
View File
@@ -40,6 +40,13 @@ Target.FixOptions = function(options)
end
v.groups = v.job or v.groups
local optionsCanInteract = v.canInteract
if optionsCanInteract then
local id = Target.CreateCanInteract(optionsCanInteract)
v.canInteract = function(...)
return Target.CanInteract(id, ...)
end
end
-- print(json.encode(v))
end
return options
+7
View File
@@ -40,6 +40,13 @@ Target.FixOptions = function(options)
options[k].action = select
options[k].job = v.job or v.groups
options[k].jobType = v.jobType
local optionsCanInteract = v.canInteract
if optionsCanInteract then
local id = Target.CreateCanInteract(optionsCanInteract)
v.canInteract = function(...)
return Target.CanInteract(id, ...)
end
end
end
return options
end
@@ -29,6 +29,13 @@ Target.FixOptions = function(options)
end
options[k].onSelect = select
options[k].groups = v.job or v.groups
local optionsCanInteract = v.canInteract
if optionsCanInteract then
local id = Target.CreateCanInteract(optionsCanInteract)
v.canInteract = function(...)
return Target.CanInteract(id, ...)
end
end
end
return options
end