diff --git a/backend/socket.js b/backend/socket.js
index ab59063..341bb4c 100644
--- a/backend/socket.js
+++ b/backend/socket.js
@@ -79,7 +79,7 @@ function socketIOServerInit(server) {
// io.to(roomID).emit("new user joined the room");
console.log(data, "joined");
let room = getRoom(roomID);
- io.to(roomID).emit(USER_JOINED_ROOM, data.username);
+ socket.to(roomID).emit(USER_JOINED_ROOM, data.username);
socket.emit(result, room.gameHistory); // room joined successfully
} else {
socket.emit(result); // room is full
diff --git a/frontend/src/context/chess-game-context.jsx b/frontend/src/context/chess-game-context.jsx
index 3df4393..7d9639a 100644
--- a/frontend/src/context/chess-game-context.jsx
+++ b/frontend/src/context/chess-game-context.jsx
@@ -12,7 +12,6 @@ const { GAME_END, CHESS_MOVE } = SOCKET_EVENTS;
export const ChessGameContext = createContext();
const reducer = (state, action) => {
- // console.log('Before', state);
try {
switch (action.type) {
case SELECT_PIECE:
@@ -78,12 +77,9 @@ const reducer = (state, action) => {
return state;
}
} catch (err) {
- console.log('Error', err);
- console.log('After', state);
- // state.chess.getBoard()
+ console.error(err);
+ return state;
}
- // console.log('After', state);
- return state;
}
function chessGameStateInit(myColor) {
@@ -107,6 +103,16 @@ const ChessGameContextProvider = ({ children }) => {
const [{ chess, chessBoard, moveHints, selected, gameHistory, currentIndex, hasGameEnded, gameEndedReason }, dispatch] = useReducer(reducer, myColor, chessGameStateInit);
const [isTimerOn, setIsTimerOn] = useState(true);
+ const chessRef = useRef(chess);
+ const moveHintsRef = useRef(moveHints);
+ const selectedRef = useRef(selected);
+ const gameHistoryRef = useRef(gameHistory);
+ const currentIndexRef = useRef(currentIndex);
+ chessRef.current = chess;
+ selectedRef.current = selected;
+ moveHintsRef.current = moveHints;
+ gameHistoryRef.current = gameHistory;
+ currentIndexRef.current = currentIndex;
const moveAudioRef = useRef(null);
const captureAudioRef = useRef(null);
@@ -116,38 +122,35 @@ const ChessGameContextProvider = ({ children }) => {
// data received through socket
function handleOpponentMove(data) {
let { from, to } = data;
- console.log(from, to, chess.get(to), chess.ascii());
- if (!chess.get(to)) {
+ if (!chessRef.current.get(to)) {
dispatch({ type: MOVE_PIECE, val: { from, to } });
moveAudioRef.current.play();
- console.log(chess.ascii())
return;
} else {
dispatch({ type: CAPTURE_PIECE, val: { from, to } });
captureAudioRef.current.play();
- console.log(chess.ascii())
return;
}
}
// called when user clicks a square
function handleSquareClick(square, emitToSocketCallback) {
- let { type, color } = chess.get(square);
- let marked = moveHints.includes(square);
+ let { type, color } = chessRef.current.get(square);
+ let marked = moveHintsRef.current.includes(square);
- if (chess.turn() === myColor) {
+ if (chessRef.current.turn() === myColor) {
if (type && color === myColor) {
return dispatch({ type: SELECT_PIECE, val: square });
}
- if (!type && selected && marked) {
+ if (!type && selectedRef.current && marked) {
dispatch({ type: MOVE_PIECE, val: { from: selected, to: square } })
- emitToSocketCallback({ from: selected, to: square })
+ emitToSocketCallback({ from: selectedRef.current, to: square })
setIsTimerOn(false)
captureAudioRef.current.play();
}
if (type && marked) {
- dispatch({ type: CAPTURE_PIECE, val: { from: selected, to: square } })
- emitToSocketCallback({ from: selected, to: square })
+ dispatch({ type: CAPTURE_PIECE, val: { from: selectedRef.current, to: square } })
+ emitToSocketCallback({ from: selectedRef.current, to: square })
setIsTimerOn(false);
moveAudioRef.current.play();
}
@@ -159,8 +162,8 @@ const ChessGameContextProvider = ({ children }) => {
function handleDrop(moveData) {
let { from, to } = moveData;
// console.log(from, to, ch ess.get(to), chess.ascii())
- if (moveHints.includes(to)) {
- if (chess.get(to)) {
+ if (moveHintsRef.current.includes(to)) {
+ if (chessRef.current.get(to)) {
dispatch({ type: CAPTURE_PIECE, val: { from: from, to: to } }); // capture piece
captureAudioRef.current.play();
// setIsTimerOn(false)
@@ -175,17 +178,17 @@ const ChessGameContextProvider = ({ children }) => {
}
function selectPiece({ square, color: pieceColor }) {
- if (pieceColor === myColor && myColor === chess.turn()) {
+ if (pieceColor === myColor && myColor === chessRef.current.turn()) {
dispatch({ type: SELECT_PIECE, val: square });
}
}
function getSquareColor(square) {
- return chess.squareColor(square) === 'light' ? "w" : "b";
+ return chessRef.current.squareColor(square) === 'light' ? "w" : "b";
}
function isSquareMarked(square) {
- return moveHints.includes(square);
+ return moveHintsRef.current.includes(square);
}
function jumpTo(index) {
@@ -193,24 +196,24 @@ const ChessGameContextProvider = ({ children }) => {
}
function getChessBoard() {
- if (currentIndex === -1 || gameHistory.length === 0) {
+ if (currentIndexRef.current === -1 || gameHistoryRef.current.length === 0) {
return new ChessModified().getBoard();
} else {
// console.log(chess);
- let currentChessBoard = new ChessModified(gameHistory[currentIndex].fen).getBoard();
+ let currentChessBoard = new ChessModified(gameHistoryRef.current[currentIndexRef.current].fen).getBoard();
return currentChessBoard;
}
}
function goBack() {
- if (currentIndex > 0) {
- jumpTo(currentIndex - 1);
+ if (currentIndexRef.current > 0) {
+ jumpTo(currentIndexRef.current - 1);
}
}
function goAhead() {
- if (currentIndex < gameHistory.length - 1) {
- jumpTo(currentIndex + 1);
+ if (currentIndexRef.current < gameHistoryRef.current.length - 1) {
+ jumpTo(currentIndexRef.current + 1);
}
}
diff --git a/frontend/src/hooks/useChess.jsx b/frontend/src/hooks/useChess.jsx
new file mode 100644
index 0000000..9398a38
--- /dev/null
+++ b/frontend/src/hooks/useChess.jsx
@@ -0,0 +1,92 @@
+import { useReducer } from "react";
+
+import { ChessModified, chessInit } from "../utils/chess"
+import { DISPATCH_EVENTS } from "../constants";
+
+const { SELECT_PIECE, MOVE_PIECE, CAPTURE_PIECE, SET_GAME_HISTORY } = DISPATCH_EVENTS
+
+let BLACK = 'b', WHITE = 'w';
+
+function chessStateInit() {
+ let chess = chessInit();
+ let moveHints = [];
+ let gameHistory = [];
+ let capturedPieces = { 'w': [], 'b': [] };
+ let selected = null;
+ // represents which move is viewed in history
+ let currentHistoryIndex = -1;
+ let hasEnded = false;
+
+ return { chess, moveHints, selected, gameHistory, currentHistoryIndex, hasEnded, capturedPieces }
+}
+
+const reducer = (state, action) => {
+ console.log(action);
+ switch (action.type) {
+ case SELECT_PIECE: {
+ let moveHints = state.chess.getMoves(action.val);
+ let selected = action.val
+ return { ...state, moveHints, selected };
+ }
+ case MOVE_PIECE: {
+ let newChess = new ChessModified(state.chess.fen());
+ console.log(newChess.ascii());
+ let updatedGameHistory = [...state.gameHistory];
+ let { san, after } = newChess.move(action.val);
+ updatedGameHistory.push({ move: san, fen: after });
+ return { ...state, chess: newChess, moveHints: [], gameHistory: updatedGameHistory, currentHistoryIndex: updatedGameHistory.length - 1, selected: null };
+ }
+ case CAPTURE_PIECE: {
+ let newChess = new ChessModified(state.chess.fen());
+ let updatedGameHistory = [...state.gameHistory];
+ let { san, after } = newChess.move(action.val);
+ updatedGameHistory.push({ move: san, fen: after });
+ return { ...state, chess: newChess, moveHints: [], gameHistory: updatedGameHistory, currentHistoryIndex: updatedGameHistory.length - 1, selected: null };
+ }
+ case SET_GAME_HISTORY: {
+ let fetchedGameHistory = action.val;
+ let newChess = new ChessModified();
+ let updatedGameHistory = [];
+ let capturedPieces = { 'w': [], 'b': [] }
+ for (let i = 0; i < fetchedGameHistory.length; i++) {
+ let { san, after, captured, color } = newChess.move(fetchedGameHistory[i]);
+ updatedGameHistory.push({ fen: after, move: san });
+ if (captured) {
+ color === WHITE ? capturedPieces[BLACK].push(captured) : capturedPieces[WHITE].push(captured);
+ }
+ }
+ return { ...state, chess: newChess, gameHistory: updatedGameHistory, currentHistoryIndex: updatedGameHistory.length - 1, capturedPieces }
+ }
+ }
+}
+
+const useChess = () => {
+ const [{ chess, moveHints, selected, gameHistory, currentHistoryIndex, capturedPieces, hasEnded }, dispatch] = useReducer(reducer, null, chessStateInit);
+
+ function selectPiece(square) {
+ dispatch({ type: SELECT_PIECE, val: square })
+ }
+
+ function movePiece(from, to) {
+ dispatch({ type: MOVE_PIECE, val: { from, to } })
+ }
+
+ function capturePiece(from, to) {
+ dispatch({ type: CAPTURE_PIECE, val: { from, to } })
+ }
+
+ function setGameHistory(gameHistory) {
+ dispatch({ type: SET_GAME_HISTORY, val: gameHistory })
+ }
+
+ return {
+ chessState: {
+ chess, selected, moveHints, gameHistory, currentHistoryIndex, capturedPieces, hasEnded
+ },
+ chessStateModifiers: {
+ selectPiece, movePiece, capturePiece, setGameHistory
+ }
+ }
+}
+
+export default useChess;
\ No newline at end of file
diff --git a/frontend/src/pages/Chess/ChessGame.jsx b/frontend/src/pages/Chess/ChessGame.jsx
index 0afaf29..74132f6 100644
--- a/frontend/src/pages/Chess/ChessGame.jsx
+++ b/frontend/src/pages/Chess/ChessGame.jsx
@@ -11,10 +11,11 @@ import ChessBoard from '../Chess/ChessBoard'
import GameHistory from '../../components/GameHistory'
import MainLoader from '../../components/MainLoader'
import { SOCKET_EVENTS } from '../../constants'
+import Timer from './Timer'
const { CONNECT, DISCONNECT, CHESS_OPPONENT_MOVE, USER_RESIGNED, JOIN_ROOM, JOIN_ROOM_ERROR, JOIN_ROOM_SUCCESS, ROOM_FULL, USER_JOINED_ROOM } = SOCKET_EVENTS;
const ChessGame = () => {
- const { setGameHistory, hasGameEnded, gameEndedReason, endGame } = useContext(ChessGameContext);
+ const { setGameHistory, hasGameEnded, gameEndedReason, endGame, handleOpponentMove, isTimerOn } = useContext(ChessGameContext);
const [gameEndedModalOpen, modalFunctions] = useDisclosure(true);
const user = getUserData();
@@ -26,6 +27,7 @@ const ChessGame = () => {
const roomID = localStorage.getItem('roomID');
const navigate = useNavigate();
const opponent = localStorage.getItem('opponent');
+ let connected = socket.id;
const exitGame = () => {
// cleanup game related data
@@ -69,10 +71,7 @@ const ChessGame = () => {
console.log('Socket disconnected due to', reason);
});
- socket.on(CHESS_OPPONENT_MOVE, () => {
- // console.log(data);
- // setIsTimerOn(true);
- })
+ socket.on(CHESS_OPPONENT_MOVE, handleOpponentMove)
socket.on(USER_JOINED_ROOM, () => {
setIsWaiting(false);
@@ -88,6 +87,10 @@ const ChessGame = () => {
}
}, []);
+ useEffect(() => {
+ console.log('Connection useEffect()');
+ }, [connected]);
+
if (!hasJoinedRoom) return (
)
@@ -111,7 +114,7 @@ const ChessGame = () => {
}
description={"description"}
/>
- {/* */}
+
{
// TODO: handle isWaiting state
@@ -137,7 +140,7 @@ const ChessGame = () => {
}
description={"description"}
/>
- {/* */}
+