Skip to content

Commit 53473ef

Browse files
committed
change semantics of enabling/disabling events
- all events are always available within game logic in the Events API - enabling / disabling events merely affects whether the client can trigger them directly
1 parent 992416a commit 53473ef

7 files changed

Lines changed: 83 additions & 81 deletions

File tree

docs/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ endTurn({ next: playerID })
5858
endTurnIf: () => ({ next: playerID })
5959
```
6060

61+
6. The semantics of enabling / disabling events has changed
62+
a bit: see https://boardgame.io/#/events for more details.
63+
6164
## v0.26.3
6265

6366
#### Features

docs/events.md

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,6 @@ The default behavior is to increment `ctx.turn` by `1`
1414
and advance `currentPlayer` to the next player according
1515
to the configured turn order (the default being a round-robin).
1616

17-
This event is enabled by default. To disable this event,
18-
pass `endTurn: false` inside your `flow` section. Note that
19-
turns can still end if you use `endTurnIf` or `movesPerTurn`.
20-
Disabling the event merely prevents you from explicitly
21-
triggering it.
22-
2317
`endTurn` also accepts an argument, which (if provided)
2418
switches the turn to the specified player.
2519

@@ -31,10 +25,6 @@ is orthogonal to a player turn (i.e. you can end the phase
3125
many times within a single turn, or you can have many
3226
turns within a single phase).
3327

34-
To disable this event, pass `endPhase: false` inside your
35-
`flow` section. Note that phases can still end if you use
36-
`endPhaseIf`.
37-
3828
`endPhase` also accepts an argument, which (if provided)
3929
switches the phase to the phase specified.
4030

@@ -77,10 +67,6 @@ const opts = {
7767
setActionPlayers(opts);
7868
```
7969

80-
!> This event is not enabled by default and must be enabled
81-
by setting `setActionPlayers: true` in the `flow` section
82-
of your game.
83-
8470
### Triggering an event from a React client.
8571

8672
Events are available through `props` inside the
@@ -116,3 +102,40 @@ moves: {
116102
};
117103
}
118104
```
105+
106+
### Enabling / Disabling events
107+
108+
An important point to note is that not all events are
109+
enabled on the client, and some need to be explicitly
110+
enabled.
111+
112+
The following table describes the defaults:
113+
114+
| Event | Default |
115+
| :--------------: | :-----: |
116+
| endTurn | true |
117+
| endPhase | true |
118+
| endGame | false |
119+
| setActionPlayers | false |
120+
121+
In order to enable an event, just add `eventName: true` to
122+
your `flow` section.
123+
124+
```js
125+
flow: {
126+
endGame: true,
127+
...
128+
}
129+
```
130+
131+
In order to disable an event, add `eventName: false`.
132+
133+
```js
134+
flow: {
135+
endPhase: false,
136+
...
137+
}
138+
```
139+
140+
!> This doesn't apply to events in game logic, inside
141+
which all events are always enabled.

examples/react/turnorder/example-militia.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import { Game } from 'boardgame.io/core';
1111

1212
const code = `{
1313
flow: {
14-
setActionPlayers: true,
1514
startingPhase: 'play',
1615
1716
phases: {
@@ -54,7 +53,7 @@ export default {
5453

5554
game: Game({
5655
flow: {
57-
setActionPlayers: true,
56+
endPhase: false,
5857
startingPhase: 'play',
5958

6059
phases: {

src/client/client.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -298,7 +298,7 @@ class _ClientImpl {
298298
);
299299

300300
this.events = createEventDispatchers(
301-
this.game.flow.eventNames,
301+
this.game.flow.enabledEventNames,
302302
this.store,
303303
this.playerID,
304304
this.credentials,

src/client/client.test.js

Lines changed: 21 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,7 @@
88

99
import { createStore } from 'redux';
1010
import { CreateGameReducer } from '../core/reducer';
11-
import {
12-
Client,
13-
GetOpts,
14-
createEventDispatchers,
15-
createMoveDispatchers,
16-
} from './client';
11+
import { Client, GetOpts, createMoveDispatchers } from './client';
1712
import { Local } from './transport/local';
1813
import { SocketIO } from './transport/socketio';
1914
import { update, sync, makeMove, gameEvent } from '../core/action-creators';
@@ -193,68 +188,46 @@ test('accepts enhancer for store', () => {
193188
expect(spyDispatcher.mock.calls).toHaveLength(1);
194189
});
195190

196-
test('event dispatchers', () => {
197-
{
191+
describe('event dispatchers', () => {
192+
test('default', () => {
198193
const game = Game({});
199-
const reducer = CreateGameReducer({ game, numPlayers: 2 });
200-
const store = createStore(reducer);
201-
const api = createEventDispatchers(game.flow.eventNames, store);
202-
expect(Object.getOwnPropertyNames(api)).toEqual(['endTurn']);
203-
expect(store.getState().ctx.turn).toBe(0);
204-
api.endTurn();
205-
expect(store.getState().ctx.turn).toBe(1);
206-
}
207-
208-
{
194+
const client = Client({ game });
195+
expect(Object.keys(client.events)).toEqual(['endTurn']);
196+
expect(client.getState().ctx.turn).toBe(0);
197+
client.events.endTurn();
198+
expect(client.getState().ctx.turn).toBe(1);
199+
});
200+
201+
test('all events', () => {
209202
const game = Game({
210203
flow: {
211204
endPhase: true,
212205
endGame: true,
213206
setActionPlayers: true,
214207
},
215208
});
216-
const reducer = CreateGameReducer({ game, numPlayers: 2 });
217-
const store = createStore(reducer);
218-
const api = createEventDispatchers(game.flow.eventNames, store);
219-
expect(Object.getOwnPropertyNames(api)).toEqual([
209+
const client = Client({ game });
210+
expect(Object.keys(client.events)).toEqual([
220211
'endTurn',
221212
'endPhase',
222213
'endGame',
223214
'setActionPlayers',
224215
]);
225-
expect(store.getState().ctx.turn).toBe(0);
226-
api.endTurn();
227-
expect(store.getState().ctx.turn).toBe(1);
228-
}
216+
expect(client.getState().ctx.turn).toBe(0);
217+
client.events.endTurn();
218+
expect(client.getState().ctx.turn).toBe(1);
219+
});
229220

230-
{
221+
test('no events', () => {
231222
const game = Game({
232223
flow: {
233224
endPhase: false,
234225
endTurn: false,
235226
},
236227
});
237-
const reducer = CreateGameReducer({ game, numPlayers: 2 });
238-
const store = createStore(reducer);
239-
const api = createEventDispatchers(game.flow.eventNames, store);
240-
expect(Object.getOwnPropertyNames(api)).toEqual([]);
241-
}
242-
243-
{
244-
const game = Game({
245-
flow: {
246-
endPhase: true,
247-
undoableMoves: ['A'],
248-
},
249-
});
250-
const reducer = CreateGameReducer({ game, numPlayers: 2 });
251-
const store = createStore(reducer);
252-
const api = createEventDispatchers(game.flow.eventNames, store);
253-
expect(Object.getOwnPropertyNames(api)).toEqual(['endTurn', 'endPhase']);
254-
expect(store.getState().ctx.turn).toBe(0);
255-
api.endTurn();
256-
expect(store.getState().ctx.turn).toBe(1);
257-
}
228+
const client = Client({ game });
229+
expect(Object.keys(client.events)).toEqual([]);
230+
});
258231
});
259232

260233
describe('move dispatchers', () => {

src/core/flow.js

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ import * as logging from './logger';
3232
* reducer will handle. Each function
3333
* has the following signature:
3434
* ({G, ctx}) => {G, ctx}
35+
* @param {...object} enabledEvents - Map of eventName -> bool indicating
36+
* which events are callable from the client
37+
* or from within moves.
3538
* @param {...object} processMove - A function that's called whenever a move is made.
3639
* (state, action, dispatch) => state.
3740
* @param {...object} optimisticUpdate - (G, ctx, move) => boolean
@@ -53,6 +56,7 @@ import * as logging from './logger';
5356
export function Flow({
5457
ctx,
5558
events,
59+
enabledEvents,
5660
init,
5761
processMove,
5862
optimisticUpdate,
@@ -61,6 +65,7 @@ export function Flow({
6165
}) {
6266
if (!ctx) ctx = () => ({});
6367
if (!events) events = {};
68+
if (!enabledEvents) enabledEvents = {};
6469
if (!init) init = state => state;
6570
if (!processMove) processMove = state => state;
6671
if (!canMakeMove) canMakeMove = () => true;
@@ -89,6 +94,7 @@ export function Flow({
8994
canUndoMove,
9095

9196
eventNames: Object.getOwnPropertyNames(events),
97+
enabledEventNames: Object.getOwnPropertyNames(enabledEvents),
9298

9399
processMove: (state, action) => {
94100
return processMove(state, action, dispatch);
@@ -663,18 +669,25 @@ export function FlowWithPhases({
663669
return conf.undoableMoves.includes(moveName);
664670
};
665671

672+
const events = {
673+
endTurn: endTurnEvent,
674+
endPhase: endPhaseEvent,
675+
endGame: endGameEvent,
676+
setActionPlayers: SetActionPlayers,
677+
};
678+
666679
let enabledEvents = {};
667680
if (endTurn) {
668-
enabledEvents['endTurn'] = endTurnEvent;
681+
enabledEvents['endTurn'] = true;
669682
}
670683
if (endPhase) {
671-
enabledEvents['endPhase'] = endPhaseEvent;
684+
enabledEvents['endPhase'] = true;
672685
}
673686
if (endGame) {
674-
enabledEvents['endGame'] = endGameEvent;
687+
enabledEvents['endGame'] = true;
675688
}
676689
if (setActionPlayers) {
677-
enabledEvents['setActionPlayers'] = SetActionPlayers;
690+
enabledEvents['setActionPlayers'] = true;
678691
}
679692

680693
return Flow({
@@ -700,7 +713,8 @@ export function FlowWithPhases({
700713
}
701714
return optimisticUpdate(G, ctx, action);
702715
},
703-
events: enabledEvents,
716+
events,
717+
enabledEvents,
704718
processMove,
705719
canMakeMove,
706720
canUndoMove,

src/core/turn-order.test.js

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ test('playOrder', () => {
196196
});
197197

198198
describe('SetActionPlayers', () => {
199-
const flow = FlowWithPhases({ setActionPlayers: true });
199+
const flow = FlowWithPhases({});
200200
const state = { ctx: flow.ctx(2) };
201201

202202
test('basic', () => {
@@ -217,10 +217,6 @@ describe('SetActionPlayers', () => {
217217

218218
test('once', () => {
219219
const game = Game({
220-
flow: {
221-
setActionPlayers: true,
222-
},
223-
224220
moves: {
225221
B: (G, ctx) => {
226222
ctx.events.setActionPlayers({ value: ['0', '1'], once: true });
@@ -243,10 +239,6 @@ describe('SetActionPlayers', () => {
243239

244240
test('allOthers', () => {
245241
const game = Game({
246-
flow: {
247-
setActionPlayers: true,
248-
},
249-
250242
moves: {
251243
B: (G, ctx) => {
252244
ctx.events.setActionPlayers({
@@ -279,8 +271,6 @@ describe('SetActionPlayers', () => {
279271

280272
test('militia', () => {
281273
const game = Game({
282-
flow: { setActionPlayers: true },
283-
284274
moves: {
285275
playMilitia: (G, ctx) => {
286276
// change which players need to act

0 commit comments

Comments
 (0)