| const socket = require("socket.io"); |
| const { SOCKET_EVENTS } = require("./constants"); |
| const { Chess } = require("chess.js"); |
| const { User } = require("./models/user"); |
| const { Game } = require("./models/game"); |
| const { nextMove } = require("./chessbot"); |
| const { |
| CHESS_MOVE, |
| CHESS_OPPONENT_MOVE, |
| JOIN_ROOM, |
| JOIN_ROOM_ERROR, |
| JOIN_ROOM_SUCCESS, |
| ROOM_FULL, |
| USER_JOINED_ROOM, |
| USER_RESIGNED, |
| GAME_END, |
| } = SOCKET_EVENTS; |
| |
| let activeRooms = new Map(); |
|
|
| |
| |
| function isValidMove(chess,moveData) { |
| let newChess = new Chess(); |
| newChess.loadPgn(chess.pgn()); |
| try { |
| newChess.move(moveData); |
| return true; |
| } catch(err) { |
| return false; |
| } |
| } |
|
|
| function createRoom(roomID, timeLimit) { |
| console.log(roomID, "created"); |
| activeRooms.set(roomID, { timeLimit, players: {}, gameHistory: [] }); |
| console.log("Currently active rooms", activeRooms.size); |
| } |
|
|
| function getRoom(roomID) { |
| return activeRooms.get(roomID); |
| } |
|
|
| function destoryRoom(roomID) { |
| activeRooms.delete(roomID); |
| } |
|
|
| |
| function addUserToRoom(roomID, socket, userDetails) { |
| console.log(userDetails); |
| let { username, color, userid } = userDetails; |
| let room = activeRooms.get(roomID); |
|
|
| if (room.players[color]) { |
| room.players[color] = { username, userid, socket }; |
| return JOIN_ROOM_SUCCESS; |
| } |
| if (Object.keys(room.players).length > 1) { |
| |
| console.log(activeRooms); |
| return ROOM_FULL; |
| } else { |
| room.players[color] = { username, userid, socket }; |
| } |
| console.log(activeRooms); |
|
|
| return JOIN_ROOM_SUCCESS; |
| } |
|
|
| |
| function socketIOServerInit(server) { |
| const io = new socket.Server(server, { |
| cors: { |
| origin: process.env.CORS_ALLOWED_HOST, |
| }, |
| }); |
|
|
| const ioBot = io.of("/chessbot"); |
|
|
| ioBot.on("connection", (socket) => { |
| let id = socket.id; |
| console.log(id, "connected on /chessbot"); |
| const chess = new Chess(); |
|
|
| socket.onAny((evt) => { |
| console.log(evt); |
| }); |
|
|
| socket.on('INIT', async (data) => { |
| if(data.color === 'b') { |
| console.log(data.color); |
| const botMove = await nextMove({position:chess.fen()}); |
| console.log({ from: botMove.substring(0, 2), to: botMove.substring(2) }); |
| chess.move({from:botMove.substring(0,2),to:botMove.substring(2)}); |
| setTimeout(() => { |
| socket.emit("CHESS_BOT_MOVE",{from:botMove.substring(0,2),to:botMove.substring(2)}) |
| }, 500); |
| } |
| }); |
|
|
| socket.on("disconnect", (reason) => { |
| console.log(id, "disconnected due to", reason); |
| }); |
|
|
| socket.on(CHESS_MOVE, async (roomID, moveData) => { |
| console.log("CHESS_MOVE"); |
| if(!isValidMove(chess,moveData)) return; |
| chess.move(moveData); |
| let move = moveData.from + moveData.to; |
| console.log(move); |
| const botMove = await nextMove({ position: chess.fen() }); |
| console.log({ from: botMove.substring(0, 2), to: botMove.substring(2) }); |
| chess.move({ from: botMove.substring(0, 2), to: botMove.substring(2) }); |
| socket.emit("CHESS_BOT_MOVE", { from: botMove.substring(0, 2), to: botMove.substring(2) }); |
| }); |
| }); |
|
|
| io.on("connection", (socket) => { |
| let id = socket.id; |
| console.log(socket.id, "connected"); |
|
|
| socket.on("disconnect", (reason) => { |
| console.log(id, "disconnected due to", reason); |
| }); |
|
|
| |
| |
| socket.on(JOIN_ROOM, (roomID, data) => { |
| if (activeRooms.has(roomID)) { |
| let result = addUserToRoom(roomID, socket, data); |
| if (result === JOIN_ROOM_SUCCESS) { |
| socket.join(roomID); |
| |
| console.log(data, "joined"); |
| let room = getRoom(roomID); |
| socket.to(roomID).emit(USER_JOINED_ROOM, data.username); |
| socket.emit(result, room.gameHistory); |
| } else { |
| socket.emit(result); |
| } |
| } else { |
| socket.emit(JOIN_ROOM_ERROR, "room does not exist"); |
| } |
| }); |
|
|
| socket.on(CHESS_MOVE, (roomID, moveData) => { |
| console.log(moveData); |
| let room = activeRooms.get(roomID); |
| room.gameHistory.push(moveData); |
| socket.to(roomID).emit(CHESS_OPPONENT_MOVE, moveData); |
| }); |
|
|
| socket.on(USER_RESIGNED, async (roomID, username) => { |
| socket.to(roomID).emit(USER_RESIGNED, username); |
| }); |
|
|
| socket.on(GAME_END, async (roomID) => { |
| console.log("Ending game..."); |
| const room = getRoom(roomID); |
| const black = room.players["b"]; |
| const white = room.players["w"]; |
| io.socketsLeave(roomID); |
| black.socket.disconnect(); |
| white.socket.disconnect(); |
|
|
| |
| let moves = room.gameHistory; |
| let chess = new Chess(); |
| for (let move of moves) { |
| let { from, to } = move; |
| chess.move({ from, to }); |
| } |
| let pgn = chess.pgn(); |
|
|
| const blackPlayerDoc = await User.findById(black.userid); |
| const whitePlayerDoc = await User.findById(white.userid); |
|
|
| let gameData = { |
| white: whitePlayerDoc.id, |
| black: blackPlayerDoc.id, |
| timeLimit: room.timeLimit, |
| roomID, |
| pgn, |
| }; |
| const gameDoc = await Game.create(gameData); |
|
|
| blackPlayerDoc.games.push(gameDoc.id); |
| await blackPlayerDoc.save(); |
| whitePlayerDoc.games.push(gameDoc.id); |
| await whitePlayerDoc.save(); |
| }); |
| }); |
| } |
|
|
| module.exports = { |
| activeRooms, |
| createRoom, |
| addUserToRoom, |
| socketIOServerInit, |
| }; |
|
|