I am creating a turn-based multiplayer board game with socket.io. If a client moved on the board, I want to disable to move once again, but I can't figure out how to achieve this.
When a client moves, it sends the board state to the server, then the server sends the board state to every connected client. Even to the one who made the move.
This is how I send the board state to the server from the client side:
sock.emit("message", board, turn); // Sending the board state to the server
canvas.removeEventListener("click", game);
This is how the server gets the updated board state and sends it to every client:
// If we recieve the board state from a client
sock.on("message", (board, turn) => {
io.emit("message", board, turn); // Sending the board state to every client who is connected
});
And this how the client code handles when it gets a new board state from the server:
sock.on("message", (board, turn) => {
this.board = board;
this.turn = turn;
render(board);
canvas.addEventListener("click", game);
setTimeout(function () {
if (winningMove(board)) {
// disable click event on both client
// tell the server that the game ended
sock.emit("end");
sock.on("end", () => {
window.alert("Game Over...");
window.location.reload();
});
}
}, 100);
});
You can use the socket.id value to uniquely identify each connected client (player/board in your case) and add logic on the server side to prevent multiple moves from the same client.
Keep track of the client that made the last move and ignore any new moves from the same client. The implementation would look like this:
// Variable to track last played client
let lastPlayedClient = null;
// If we recieve the board state from a client
sock.on("message", (board, turn) => {
// Ensure move is made by different client
if (lastPlayedClient !== sock.id) {
// Update last played client to current client id
lastPlayedClient = sock.id;
io.emit("message", board, turn); // Sending the board state to every client who is connected
}
});
On the server side, add logic to identify the client who has to make the next move. Then allow only that client to make the next move. Ignore moves made by any other client. The implementation would look like this:
// Variable to track client id of next player
let nextPlayer = yourLogicToIdentifyNextPlayer();
// If we recieve the board state from a client
sock.on("message", (board, turn) => {
// Ensure move is made by the identified client only
if (nextPlayer === sock.id) {
io.emit("message", board, turn); // Sending the board state to every client who is connected
}
});
To improve user experience, you can disable input on the board on the frontend as soon as the first move is made.
Ref: Socket#id
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With