Files
community_bridge/lib/entities/client/client_entity_actions.lua
T
gononono64 38d0d5527a New features and cleanup
Added Networked Markers
Added Anim module
Added framework default file for things that are native to game related to player
Started on a batch network event trigger to allow for single event call for multiple events

Updated params notation for ids
Removed prints from client_entity + actions + ext
2025-05-09 19:06:50 -05:00

137 lines
6.8 KiB
Lua

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