UNPKG

2.37 kBJavaScriptView Raw
1/**
2 * So we have lots of actions that come to us from the nextActions queue in the reducer. Some of
3 * them can be dispatched as-is, but many of them require us to run an action creator function to
4 * e.g. decrypt or encrypt something as is appropriate. This middleware detects such actions and
5 * sees if we have a cooresponding action based on a simple naming convention.
6 *
7 * actions.SEED_RNG_DECRYPT => actions.seedRngDecryptAction
8 */
9
10import * as actions from "@cardcore/game";
11
12const actionMap = {};
13for (const [key, value] of Object.entries(actions)) {
14 if (typeof value !== "string" || key !== value) {
15 continue;
16 }
17 const camelCase = value
18 .split("_")
19 .map(word => word[0].toUpperCase() + word.slice(1).toLowerCase())
20 .join("");
21 const actionCreator = camelCase[0].toLowerCase() + camelCase.slice(1);
22 if (actions[actionCreator]) {
23 actionMap[value] = actions[actionCreator];
24 }
25}
26
27/**
28 * two kinds of actions are allowed - you can either be a human that did an action on your turn or you can be a computer handling the most recent action in nextactions
29 */
30export function checkActionAllowed(state, action) {
31 // non-game actions are always allowed
32 if (!actions[action.type]) {
33 return;
34 }
35 // also if we don't have a turn order yet, nbd
36 if (!state.game || !state.game.turn) {
37 return;
38 }
39 const sender = action._sender || state.client.keys.id;
40 if (state.game.nextActions.length > 0) {
41 const queueUser = state.game.nextActions[0].playerId;
42 if (sender !== queueUser) {
43 throw new Error(`queue wants user ${queueUser} but user ${sender} acted`);
44 }
45 }
46 // no queue, check if it's an allowed action
47 else if (state.game.allowedActions[action.type] !== true) {
48 throw new Error(
49 `${sender} attempted to do non-allowed action ${action.type}`
50 );
51 } else if (state.game.turn !== sender) {
52 throw new Error(
53 `${sender} acted out of turn; it's ${state.game.turn}'s turn`
54 );
55 }
56}
57
58export default function gameActionMiddleware(store) {
59 return next => {
60 return action => {
61 const state = store.getState();
62 checkActionAllowed(state, action);
63 if (
64 !state.client.loadingState &&
65 actionMap[action.type] &&
66 action._fromQueue
67 ) {
68 action = actionMap[action.type](action);
69 }
70 return next(action);
71 };
72 };
73}