Skip to content

Commit 2a781a2

Browse files
author
Joanna May
authored
Merge pull request #21 from chickensoft-games/feat/start-stop-api
feat: restore start and stop api
2 parents 13a3975 + c7efdd3 commit 2a781a2

File tree

12 files changed

+147
-2
lines changed

12 files changed

+147
-2
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
Chickensoft.LogicBlocks/nupkg/
2+
Chickensoft.LogicBlocks.Generator/nupkg/
23

34
Chickensoft.LogicBlocks.Tests/coverage/*
45
!Chickensoft.LogicBlocks.Tests/coverage/.gdignore

Chickensoft.LogicBlocks.Generator/Chickensoft.LogicBlocks.Generator.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
<RootNamespace>Chickensoft.LogicBlocks.Generator</RootNamespace>
1010
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
1111
<NoWarn>NU5128</NoWarn>
12+
<OutputPath>./nupkg</OutputPath>
1213

1314
<Title>LogicBlocks Generator</Title>
1415
<Version>3.2.0</Version>

Chickensoft.LogicBlocks.Tests/badges/branch_coverage.svg

Lines changed: 1 addition & 1 deletion
Loading

Chickensoft.LogicBlocks.Tests/badges/line_coverage.svg

Lines changed: 1 addition & 1 deletion
Loading

Chickensoft.LogicBlocks.Tests/test/fixtures/FakeLogicBlock.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,13 @@ public OnEnterState(IContext context, Action<State?> onEnter) :
8989
OnEnter<OnEnterState>(onEnter);
9090
}
9191
}
92+
93+
public record OnExitState : State {
94+
public OnExitState(IContext context, Action<State?> onExit) :
95+
base(context) {
96+
OnExit<OnExitState>(onExit);
97+
}
98+
}
9299
}
93100

94101
public static class Output {

Chickensoft.LogicBlocks.Tests/test/fixtures/FakeLogicBlock.g.puml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ state "FakeLogicBlock State" as Chickensoft_LogicBlocks_Tests_Fixtures_FakeLogic
77
state "NothingState" as Chickensoft_LogicBlocks_Tests_Fixtures_FakeLogicBlock_State_NothingState
88
state "Custom" as Chickensoft_LogicBlocks_Tests_Fixtures_FakeLogicBlock_State_Custom
99
state "OnEnterState" as Chickensoft_LogicBlocks_Tests_Fixtures_FakeLogicBlock_State_OnEnterState
10+
state "OnExitState" as Chickensoft_LogicBlocks_Tests_Fixtures_FakeLogicBlock_State_OnExitState
1011
Chickensoft_LogicBlocks_Tests_Fixtures_FakeLogicBlock_State : OnInputOneOutputOne
1112
Chickensoft_LogicBlocks_Tests_Fixtures_FakeLogicBlock_State : OnInputTwoOutputTwo
1213
Chickensoft_LogicBlocks_Tests_Fixtures_FakeLogicBlock_State : OnNoNewStateOutputOne

Chickensoft.LogicBlocks.Tests/test/fixtures/FakeLogicBlockAsync.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,13 @@ public OnEnterState(IContext context, Func<State?, Task> onEnter) :
8989
OnEnter<OnEnterState>(onEnter);
9090
}
9191
}
92+
93+
public record OnExitState : State {
94+
public OnExitState(IContext context, Func<State?, Task> onExit) :
95+
base(context) {
96+
OnExit<OnExitState>(onExit);
97+
}
98+
}
9299
}
93100

94101
public static class Output {

Chickensoft.LogicBlocks.Tests/test/src/LogicBlockAsyncTest.cs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,4 +217,42 @@ public async Task StartsManuallyAndIgnoresStartWhenProcessing() {
217217

218218
enterCalled.ShouldBeTrue();
219219
}
220+
221+
[Fact]
222+
public async Task StartEntersState() {
223+
var enterCalled = false;
224+
var block = new FakeLogicBlockAsync() {
225+
InitialState = (context) =>
226+
new FakeLogicBlockAsync.State.OnEnterState(
227+
context, (previous) => {
228+
enterCalled = true;
229+
return Task.CompletedTask;
230+
})
231+
};
232+
233+
enterCalled.ShouldBeFalse();
234+
235+
await block.Start();
236+
237+
enterCalled.ShouldBeTrue();
238+
}
239+
240+
[Fact]
241+
public async Task StopExitsState() {
242+
var exitCalled = false;
243+
var block = new FakeLogicBlockAsync() {
244+
InitialState = (context) =>
245+
new FakeLogicBlockAsync.State.OnExitState(
246+
context, (previous) => {
247+
exitCalled = true;
248+
return Task.CompletedTask;
249+
})
250+
};
251+
252+
exitCalled.ShouldBeFalse();
253+
254+
await block.Stop();
255+
256+
exitCalled.ShouldBeTrue();
257+
}
220258
}

Chickensoft.LogicBlocks.Tests/test/src/LogicBlockTest.cs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,4 +328,38 @@ public void StartsManuallyAndIgnoresStartWhenProcessing() {
328328

329329
enterCalled.ShouldBeTrue();
330330
}
331+
332+
[Fact]
333+
public void StartEntersState() {
334+
var enterCalled = false;
335+
var block = new FakeLogicBlock() {
336+
InitialState = (context) =>
337+
new FakeLogicBlock.State.OnEnterState(
338+
context, (previous) => enterCalled = true
339+
)
340+
};
341+
342+
enterCalled.ShouldBeFalse();
343+
344+
block.Start();
345+
346+
enterCalled.ShouldBeTrue();
347+
}
348+
349+
[Fact]
350+
public void StopExitsState() {
351+
var exitCalled = false;
352+
var block = new FakeLogicBlock() {
353+
InitialState = (context) =>
354+
new FakeLogicBlock.State.OnExitState(
355+
context, (previous) => exitCalled = true
356+
)
357+
};
358+
359+
exitCalled.ShouldBeFalse();
360+
361+
block.Stop();
362+
363+
exitCalled.ShouldBeTrue();
364+
}
331365
}

Chickensoft.LogicBlocks/src/LogicBlock.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,21 @@ public interface ILogicBlock<TState> :
2626
TState GetInitialState(Logic<
2727
TState, Func<object, TState>, TState, Action<TState?>
2828
>.IContext context);
29+
30+
/// <summary>
31+
/// Starts the logic block by entering the current state. If the logic block
32+
/// hasn't initialized yet, this will create the initial state before entering
33+
/// it.
34+
/// </summary>
35+
void Start();
36+
37+
/// <summary>
38+
/// Stops the logic block by exiting the current state. For best results,
39+
/// don't continue to give inputs to the logic block after stopping it.
40+
/// Otherwise, you might end up firing the exit handler of a state more than
41+
/// once.
42+
/// </summary>
43+
void Stop();
2944
}
3045

3146
/// <summary>
@@ -108,6 +123,13 @@ internal override TState Process() {
108123
return Value;
109124
}
110125

126+
/// <inheritdoc />
127+
public void Start() =>
128+
Value.Enter(previous: null, onError: (e) => AddError(e));
129+
130+
/// <inheritdoc />
131+
public void Stop() => Value.Exit(next: null, onError: (e) => AddError(e));
132+
111133
internal override Func<object, TState> GetInputHandler<TInputType>()
112134
=> (input) => {
113135
if (Value is IGet<TInputType> stateWithHandler) {

Chickensoft.LogicBlocks/src/LogicBlockAsync.cs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,21 @@ TState GetInitialState(
3131
Func<TState?, Task>
3232
>.IContext context
3333
);
34+
35+
/// <summary>
36+
/// Starts the logic block by entering the current state. If the logic block
37+
/// hasn't initialized yet, this will create the initial state before entering
38+
/// it.
39+
/// </summary>
40+
Task Start();
41+
42+
/// <summary>
43+
/// Stops the logic block by exiting the current state. For best results,
44+
/// don't continue to give inputs to the logic block after stopping it.
45+
/// Otherwise, you might end up firing the exit handler of a state more than
46+
/// once.
47+
/// </summary>
48+
Task Stop();
3449
}
3550

3651
/// <summary>
@@ -136,6 +151,13 @@ private async Task<TState> ProcessInputs() {
136151
return Value;
137152
}
138153

154+
/// <inheritdoc />
155+
public Task Start() =>
156+
Value.Enter(previous: null, onError: (e) => AddError(e));
157+
158+
/// <inheritdoc />
159+
public Task Stop() => Value.Exit(next: null, onError: (e) => AddError(e));
160+
139161
internal override Func<object, Task<TState>> GetInputHandler<TInputType>()
140162
=> (input) => {
141163
if (Value is IGet<TInputType> stateWithHandler) {

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -678,6 +678,18 @@ Or, in the case of an async logic block:
678678
await logic.Start();
679679
```
680680

681+
Likewise, when you are done with your logic block, you can run the exit callbacks for the final state by calling `Stop`.
682+
683+
```csharp
684+
logic.Stop(); // Runs OnExit callbacks for the current (presumably final) state.
685+
```
686+
687+
Or, for an async logic block:
688+
689+
```csharp
690+
await logic.Stop();
691+
```
692+
681693
### 🧪 Testing
682694

683695
You can mock a logic block, its bindings, and its context.

0 commit comments

Comments
 (0)