You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

149 lines
4.3 KiB

3 years ago
-- ------------------------------------------------------------------------------ --
-- TradeSkillMaster --
-- https://tradeskillmaster.com --
-- All Rights Reserved - Detailed license information included with addon. --
-- ------------------------------------------------------------------------------ --
local TSM = select(2, ...) ---@type TSM
local State = TSM.Init("Util.FSMClasses.State") ---@class Util.FSMClasses.State
3 years ago
local LibTSMClass = TSM.Include("LibTSMClass")
local TempTable = TSM.Include("Util.TempTable")
local FSMState = LibTSMClass.DefineClass("FSMState") ---@class FSMState
3 years ago
local private = {
eventTransitionHandlerCache = {},
}
-- ============================================================================
-- Class Meta Methods
-- ============================================================================
function State.Create(name)
return FSMState(name)
end
function State.IsInstance(obj)
return obj:__isa(FSMState)
end
-- ============================================================================
-- Class Meta Methods
-- ============================================================================
function FSMState:__init(name)
3 years ago
self._name = name
self._onEnterHandler = nil
self._onExitHandler = nil
self._transitionValid = {}
self._events = {}
end
-- ============================================================================
-- Public Class Methods
-- ============================================================================
---Set the OnEnter handler.
---
---This function is called upon entering the state.
---@param handler function The handler function to call
---@return FSMState @The FSM state object
function FSMState:SetOnEnter(handler)
assert(type(handler) == "function")
3 years ago
self._onEnterHandler = handler
return self
end
---Set the OnExit handler.
---
---This function is called upon existing the state.
---@param handler function The handler function to call
---@return FSMState @The FSM state object
function FSMState:SetOnExit(handler)
assert(type(handler) == "function")
3 years ago
self._onExitHandler = handler
return self
end
---Add a transition.
---@param toState string The state this transition goes to
---@return FSMState @The FSM state object
function FSMState:AddTransition(toState)
3 years ago
assert(not self._transitionValid[toState], "transition already exists")
self._transitionValid[toState] = true
return self
end
---Add a handled event.
---@param event string The name of the event
---@param handler function The function called when the event occurs
---@return FSMState @The FSM state object
function FSMState:AddEvent(event, handler)
3 years ago
assert(not self._events[event], "event already exists")
self._events[event] = handler
return self
end
---Add a simple event-based transition.
---@param event string The event name
---@param toState string The state to transition to
---@return FSMState @The FSM state object
function FSMState:AddEventTransition(event, toState)
3 years ago
if not private.eventTransitionHandlerCache[toState] then
private.eventTransitionHandlerCache[toState] = function(context, ...)
return toState, ...
end
end
return self:AddEvent(event, private.eventTransitionHandlerCache[toState])
end
-- ============================================================================
-- Private Class Methods
-- ============================================================================
function FSMState:_GetName()
3 years ago
return self._name
end
function FSMState:_ToStateIterator()
3 years ago
local temp = TempTable.Acquire()
for toState in pairs(self._transitionValid) do
tinsert(temp, toState)
end
return TempTable.Iterator(temp)
end
function FSMState:_IsTransitionValid(toState)
3 years ago
return self._transitionValid[toState]
end
function FSMState:_HasEventHandler(event)
3 years ago
return self._events[event] and true or false
end
function FSMState:_ProcessEvent(event, context, ...)
3 years ago
return self:_HandlerHelper(self._events[event], context, ...)
end
function FSMState:_Enter(context, ...)
3 years ago
return self:_HandlerHelper(self._onEnterHandler, context, ...)
end
function FSMState:_Exit(context)
3 years ago
return self:_HandlerHelper(self._onExitHandler, context)
end
function FSMState:_HandlerHelper(handler, context, ...)
3 years ago
if type(handler) == "function" then
return handler(context, ...)
elseif handler ~= nil then
error("Invalid handler: "..tostring(handler))
end
end