Last active
May 31, 2020 12:26
-
-
Save fanhexin/e25244781de09daa51e6104e00186081 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
namespace Game.Util | |
{ | |
public class FluentFsm<TState, TEvent> | |
where TState : Enum | |
where TEvent : Enum | |
{ | |
readonly Dictionary<TState, State> _states = new Dictionary<TState, State>(); | |
readonly Dictionary<TEvent, TState> _anyStateTransitions = new Dictionary<TEvent, TState>(); | |
public TState CurState { get; private set; } | |
public FluentFsm(TState defaultState) | |
{ | |
CurState = defaultState; | |
} | |
public TransitionBuilder<FluentFsm<TState, TEvent>> When(TEvent ev) | |
{ | |
return new TransitionBuilder<FluentFsm<TState, TEvent>>(this, ev, _anyStateTransitions); | |
} | |
public StateBuilder Define(TState state) | |
{ | |
var s = new State(); | |
_states[state] = s; | |
return new StateBuilder(s); | |
} | |
public void Fire(TEvent ev) | |
{ | |
if (_anyStateTransitions.TryGetValue(ev, out TState state)) | |
{ | |
ToState(state); | |
return; | |
} | |
State curState = _states[CurState]; | |
if (curState.Transitions == null) | |
{ | |
return; | |
} | |
if (!curState.Transitions.TryGetValue(ev, out state)) | |
{ | |
return; | |
} | |
ToState(state); | |
} | |
public void Update() | |
{ | |
_states[CurState].OnUpdate?.Invoke(); | |
} | |
void ToState(TState state) | |
{ | |
State curState = _states[CurState]; | |
curState.OnExit?.Invoke(); | |
CurState = state; | |
curState = _states[CurState]; | |
curState.OnEnter?.Invoke(); | |
} | |
public struct StateBuilder | |
{ | |
private readonly State _state; | |
public StateBuilder(State state) | |
{ | |
_state = state; | |
} | |
public StateBuilder OnEnter(Action onEnter) | |
{ | |
_state.OnEnter = onEnter; | |
return this; | |
} | |
public StateBuilder OnExit(Action onExit) | |
{ | |
_state.OnExit = onExit; | |
return this; | |
} | |
public StateBuilder OnUpdate(Action onUpdate) | |
{ | |
_state.OnUpdate = onUpdate; | |
return this; | |
} | |
public TransitionBuilder<StateBuilder> When(TEvent ev) | |
{ | |
if (_state.Transitions == null) | |
{ | |
_state.Transitions = new Dictionary<TEvent, TState>(); | |
} | |
return new TransitionBuilder<StateBuilder>(this, ev, _state.Transitions); | |
} | |
} | |
public struct TransitionBuilder <T> | |
{ | |
private readonly TEvent _ev; | |
private readonly Dictionary<TEvent, TState> _transitions; | |
private readonly T _returnInstance; | |
public TransitionBuilder(T returnInstance, TEvent ev, Dictionary<TEvent, TState> transitions) | |
{ | |
_ev = ev; | |
_transitions = transitions; | |
_returnInstance = returnInstance; | |
} | |
public T To(TState state) | |
{ | |
_transitions[_ev] = state; | |
return _returnInstance; | |
} | |
} | |
public class State | |
{ | |
public Action OnEnter; | |
public Action OnExit; | |
public Action OnUpdate; | |
public Dictionary<TEvent, TState> Transitions; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment