|
|
|
|
-- ------------------------------------------------------------------------------ --
|
|
|
|
|
-- 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
|
|
|
|
|
local LibTSMClass = TSM.Include("LibTSMClass")
|
|
|
|
|
local TempTable = TSM.Include("Util.TempTable")
|
|
|
|
|
local FSMState = LibTSMClass.DefineClass("FSMState") ---@class FSMState
|
|
|
|
|
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)
|
|
|
|
|
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")
|
|
|
|
|
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")
|
|
|
|
|
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)
|
|
|
|
|
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)
|
|
|
|
|
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)
|
|
|
|
|
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()
|
|
|
|
|
return self._name
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function FSMState:_ToStateIterator()
|
|
|
|
|
local temp = TempTable.Acquire()
|
|
|
|
|
for toState in pairs(self._transitionValid) do
|
|
|
|
|
tinsert(temp, toState)
|
|
|
|
|
end
|
|
|
|
|
return TempTable.Iterator(temp)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function FSMState:_IsTransitionValid(toState)
|
|
|
|
|
return self._transitionValid[toState]
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function FSMState:_HasEventHandler(event)
|
|
|
|
|
return self._events[event] and true or false
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function FSMState:_ProcessEvent(event, context, ...)
|
|
|
|
|
return self:_HandlerHelper(self._events[event], context, ...)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function FSMState:_Enter(context, ...)
|
|
|
|
|
return self:_HandlerHelper(self._onEnterHandler, context, ...)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function FSMState:_Exit(context)
|
|
|
|
|
return self:_HandlerHelper(self._onExitHandler, context)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
function FSMState:_HandlerHelper(handler, context, ...)
|
|
|
|
|
if type(handler) == "function" then
|
|
|
|
|
return handler(context, ...)
|
|
|
|
|
elseif handler ~= nil then
|
|
|
|
|
error("Invalid handler: "..tostring(handler))
|
|
|
|
|
end
|
|
|
|
|
end
|