From 91ecdbcf457c09961fe14744c4862fbc19d41242 Mon Sep 17 00:00:00 2001 From: Zuev Vladimir Date: Fri, 26 Jan 2024 19:13:30 +0100 Subject: [PATCH] #13 Transit chore to wait state upon enter events specified in ChoreList config. --- .../Chores/States/ChoreStateEventsTest.cs | 2 +- .../States/DisableChoreStateTransitionTest.cs | 17 +++++++ .../Multiplayer/States/StatesManagerTest.cs | 44 ++++++++++++++++--- .../Chores/Types/StateTransitionConfig.cs | 2 - .../States/DisableChoreStateTransition.cs | 2 +- .../Multiplayer/States/StatesManager.cs | 7 +-- 6 files changed, 62 insertions(+), 12 deletions(-) diff --git a/src/MultiplayerMod.Test/Game/Chores/States/ChoreStateEventsTest.cs b/src/MultiplayerMod.Test/Game/Chores/States/ChoreStateEventsTest.cs index 3d3e6973..5eb2c8b5 100644 --- a/src/MultiplayerMod.Test/Game/Chores/States/ChoreStateEventsTest.cs +++ b/src/MultiplayerMod.Test/Game/Chores/States/ChoreStateEventsTest.cs @@ -138,7 +138,7 @@ StateTransitionConfig config var smi = (StateMachine.Instance) chore.GetType().GetProperty("smi").GetValue(chore); smi.stateMachine.GetState("root").enterActions?.Clear(); smi.stateMachine.GetState("root.delivering")?.enterActions?.Clear(); - var state = smi.stateMachine.GetState("root." + config.StateToMonitorName); + var state = config.GetMonitoredState(smi.stateMachine); state.enterActions?.Clear(); chore.Begin( new Chore.Precondition.Context { diff --git a/src/MultiplayerMod.Test/Multiplayer/Patches/Chores/States/DisableChoreStateTransitionTest.cs b/src/MultiplayerMod.Test/Multiplayer/Patches/Chores/States/DisableChoreStateTransitionTest.cs index 873d8878..5f28a264 100644 --- a/src/MultiplayerMod.Test/Multiplayer/Patches/Chores/States/DisableChoreStateTransitionTest.cs +++ b/src/MultiplayerMod.Test/Multiplayer/Patches/Chores/States/DisableChoreStateTransitionTest.cs @@ -28,6 +28,23 @@ public void SetUp() { Singleton.Instance.Clear(); } + [Test, TestCaseSource(nameof(EnterTestArgs))] + public void ClientStateEnter_DisablesTransition( + Type choreType, + Func choreArgsFunc, + Func> stateTransitionArgsFunc, + StateTransitionConfig config + ) { + var statesManager = Runtime.Instance.Dependencies.Get(); + statesManager.CalledWithStates.Clear(); + + var chore = CreateChore(choreType, choreArgsFunc.Invoke()); + + var smi = statesManager.GetSmi(chore); + var expectedState = config.GetMonitoredState(smi.stateMachine); + Assert.Contains(expectedState, statesManager.CalledWithStates); + } + [Test, TestCaseSource(nameof(ExitTestArgs))] public void ClientStateExit_DisablesTransition( Type choreType, diff --git a/src/MultiplayerMod.Test/Multiplayer/States/StatesManagerTest.cs b/src/MultiplayerMod.Test/Multiplayer/States/StatesManagerTest.cs index c081acf5..189a519f 100644 --- a/src/MultiplayerMod.Test/Multiplayer/States/StatesManagerTest.cs +++ b/src/MultiplayerMod.Test/Multiplayer/States/StatesManagerTest.cs @@ -22,9 +22,14 @@ public static void OneTimeSetUp() { [SetUp] public void SetUp() { CreateTestData(); + StateMachine.Instance.error = false; } - [Test, TestCaseSource(nameof(ExitTestArgs))] + protected static IEnumerable TestCases() { + return ExitTestArgs().Union(EnterTestArgs()); + } + + [Test, TestCaseSource(nameof(TestCases))] public void AllowTransitionPreparesWaitHostState( Type choreType, Func choreArgsFunc, @@ -50,21 +55,50 @@ StateTransitionConfig config Assert.AreEqual(expectedDictionary, waitHostState.ParametersArgs.Get(smi)); } + [Test, TestCaseSource(nameof(EnterTestArgs))] + public void EnterArgs_DisableChoreStateTransition( + Type choreType, + Func choreArgsFunc, + Func> stateTransitionArgsFunc, + StateTransitionConfig config + ) { + var sm = Singleton.Instance.CreateStateMachine(GetStatesType(choreType)); + sm.GetState("root").events?.Clear(); + var statesManager = Runtime.Instance.Dependencies.Get(); + var stateToBeSynced = config.GetMonitoredState(sm); + statesManager.ReplaceWithWaitState(stateToBeSynced); + var chore = CreateChore(choreType, choreArgsFunc.Invoke()); + var smi = statesManager.GetSmi(chore); + + smi.GoTo(stateToBeSynced); + + var waitHostState = (dynamic) statesManager.GetWaitHostState(chore); + Assert.AreEqual(waitHostState, smi.GetCurrentState()); + } + [Test, TestCaseSource(nameof(ExitTestArgs))] - public void DisableChoreStateTransition( + public void ExitArgs_DisableChoreStateTransition( Type choreType, Func choreArgsFunc, Func> stateTransitionArgsFunc, StateTransitionConfig config ) { var sm = Singleton.Instance.CreateStateMachine(GetStatesType(choreType)); + sm.defaultState = sm.GetState("root"); + sm.GetState("root.delivering")?.enterActions?.Clear(); var statesManager = Runtime.Instance.Dependencies.Get(); - statesManager - .ReplaceWithWaitState(sm.GetState("root")); + var stateToBeSynced = config.GetMonitoredState(sm); + statesManager.ReplaceWithWaitState(stateToBeSynced); var chore = CreateChore(choreType, choreArgsFunc.Invoke()); var smi = statesManager.GetSmi(chore); + chore.Begin( + new Chore.Precondition.Context { + consumerState = new ChoreConsumerState(Minion.GetComponent()), + data = PickupableGameObject.GetComponent() + } + ); - smi.GoTo("root." + config.StateToMonitorName); + smi.GoTo(stateToBeSynced); var waitHostState = (dynamic) statesManager.GetWaitHostState(chore); Assert.AreEqual(waitHostState, smi.GetCurrentState()); diff --git a/src/MultiplayerMod/Game/Chores/Types/StateTransitionConfig.cs b/src/MultiplayerMod/Game/Chores/Types/StateTransitionConfig.cs index 5f5def4d..a379a6a5 100644 --- a/src/MultiplayerMod/Game/Chores/Types/StateTransitionConfig.cs +++ b/src/MultiplayerMod/Game/Chores/Types/StateTransitionConfig.cs @@ -9,8 +9,6 @@ public record StateTransitionConfig( string[] ParameterName ) { - /// TODO: Adjust client logic to wait until receives args from the host. - /// /// TODO: Execute command on the client public static StateTransitionConfig OnEnter(string stateName, params string[] parameterName) => new(TransitionTypeEnum.Enter, stateName, null, parameterName); diff --git a/src/MultiplayerMod/Multiplayer/Patches/Chores/States/DisableChoreStateTransition.cs b/src/MultiplayerMod/Multiplayer/Patches/Chores/States/DisableChoreStateTransition.cs index f18ca3e8..c292f409 100644 --- a/src/MultiplayerMod/Multiplayer/Patches/Chores/States/DisableChoreStateTransition.cs +++ b/src/MultiplayerMod/Multiplayer/Patches/Chores/States/DisableChoreStateTransition.cs @@ -31,7 +31,7 @@ public static void InitializeStatesPatch(StateMachine __instance) { var config = ChoreList.Config[__instance.GetType().DeclaringType].StatesTransitionSync; foreach (var stateTransitionConfig in config.StateTransitionConfigs.Where( - it => it.TransitionType == TransitionTypeEnum.Exit + it => it.TransitionType is TransitionTypeEnum.Exit or TransitionTypeEnum.Enter )) { var stateToBeSynced = stateTransitionConfig.GetMonitoredState(__instance); Runtime.Instance.Dependencies.Get().ReplaceWithWaitState(stateToBeSynced); diff --git a/src/MultiplayerMod/Multiplayer/States/StatesManager.cs b/src/MultiplayerMod/Multiplayer/States/StatesManager.cs index 5f1fca91..e151b529 100644 --- a/src/MultiplayerMod/Multiplayer/States/StatesManager.cs +++ b/src/MultiplayerMod/Multiplayer/States/StatesManager.cs @@ -45,7 +45,7 @@ public void InjectWaitHostState(StateMachine sm) { Activator.CreateInstance(genericType, sm); } - public object GetWaitHostState(Chore chore) { + public StateMachine.BaseState GetWaitHostState(Chore chore) { return GetWaitHostState(GetSmi(chore)); } @@ -54,10 +54,11 @@ public StateMachine.Instance GetSmi(Chore chore) { .GetValue(chore); } - private object GetWaitHostState(StateMachine.Instance smi) => smi.stateMachine.GetState("root." + StateName); + private static StateMachine.BaseState GetWaitHostState(StateMachine.Instance smi) => + smi.stateMachine.GetState("root." + StateName); private static void TransitToWaitState(StateMachine.Instance smi) { - smi.GoTo("root." + StateName); + smi.GoTo(GetWaitHostState(smi)); } }