Since one user can take one or more seats, actions should specify which player is doing it. Then, you should include something like this in your reducer:
if (!playerValidation.canMoveAsPlayer(action.player)) throw new Error('Not your turn');
Check for invalid input or moves in reducer
if (victoriousPlayer !== -1) throw new Error('Game is already over');
if (column < 0 || column >= board[0].length) throw new Error('Invalid column');
Reducer can use provided RandomGenerator to generate random numbers.
You CANNOT use Math.random, as then reducer wouldn't be pure, and every client would generate a different random number, leading to a desync.
if (action.type === "newGame") {
return {
currentPlayer: random.int(2),
...
}
}
You can use IHiddenObjects<Type> to keep a store of hidden objects, which can be made visible to some players.
For example, you can create a hand of cards:
for (const card of hand) {
objects.addObject(card.id, card.id % 4 === 0 ? 'skull' : 'flower');
}
To create a hidden store with ids that correspond to a string.
Remember that if a client saw value of given object, or if you are creating objects in predictable way
(like in this sample, card.id = 0 will be always a skull)
You should make sure that ids are randomized so client can't infer what value is under given id - you can use shuffleAndHide method
This will will shuffle internal values of given array of ids
objects.shuffleAndHide(
player.hand.map(card => card.id),
visibleForPlayerId
);
So if you start with:
0 -> skull 1 -> flower 2 -> flower 3 -> flower
Calling objects.shuffleAndHide([0,1,2,3], 0);
will hide these objects for all player except player 0, and will cause values of these objects to shuffle, so you can end with:
0 -> flower 1 -> flower 2 -> skull 3 -> flower
(or any other combination)
Clients will only get values of objects that are marked as visible for them, server keeps all these objects. If an action will cause an object to become visible for given client, data about it will be sent to that client together with that action.
Client can get info about value visible to him using hiddenObjectsStore
const object = props.client.hiddenObjectsStore(state => state.objects[props.id]);