fix: add error handling for making moves
This commit is contained in:
@@ -40,7 +40,7 @@ const ChessBoard: React.FC<{
|
||||
chess: Chess;
|
||||
makeMove: (move: Move) => void;
|
||||
blackPerspective?: boolean;
|
||||
disabled: boolean;
|
||||
disabled?: boolean;
|
||||
}> = ({ chess, makeMove, blackPerspective, disabled }) => {
|
||||
const { width, height } = useWindowSize();
|
||||
const [activeTile, setActiveTile] = useState<number>(-1);
|
||||
@@ -92,12 +92,13 @@ const ChessBoard: React.FC<{
|
||||
|
||||
makeMove(moveObj);
|
||||
setActiveTile(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (tileProps[tile].piece == null) return setActiveTile(-1);
|
||||
|
||||
if (tile == activeTile) setActiveTile(-1);
|
||||
else setActiveTile(tile);
|
||||
console.log({ tile: algebraic(tile), activeTile: algebraic(activeTile) });
|
||||
setActiveTile(tile == activeTile ? -1 : tile);
|
||||
};
|
||||
|
||||
const sendPromotionMove = (promotion: PiecePromotionType) => {
|
||||
|
||||
@@ -7,6 +7,7 @@ import useCopyToClipboard from "../utils/useCopyToClipboard";
|
||||
import { socket } from "../sockets/socket";
|
||||
import { CopyIcon } from "../utils/icons";
|
||||
import Show from "../utils/Show";
|
||||
import ErrorNorification from "../utils/ErrorNotification";
|
||||
|
||||
const Game = () => {
|
||||
const navigate = useNavigate();
|
||||
@@ -18,12 +19,9 @@ const Game = () => {
|
||||
const [chess] = useState(Chess.load());
|
||||
const [game, setGame] = useState(false);
|
||||
const [, setRerender] = useState(false);
|
||||
const [err, setErr] = useState<Error>();
|
||||
|
||||
const makeMove = (move: Move) => {
|
||||
socket.emit("make move", id, move);
|
||||
chess.makeMove(move);
|
||||
setRerender((prev) => !prev);
|
||||
};
|
||||
const makeMove = (move: Move) => socket.emit("make move", id, move);
|
||||
|
||||
useEffect(() => {
|
||||
console.log({ id, color });
|
||||
@@ -51,6 +49,10 @@ const Game = () => {
|
||||
});
|
||||
});
|
||||
|
||||
socket.on("move error", (message: string) => {
|
||||
setErr(new Error(message));
|
||||
});
|
||||
|
||||
socket.on("start game", () => setGame(true));
|
||||
|
||||
socket.on("receive move", (move: Move) => {
|
||||
@@ -65,12 +67,16 @@ const Game = () => {
|
||||
|
||||
return (
|
||||
<Show when={game} fallback={<Waiting id={id} />}>
|
||||
<ErrorNorification
|
||||
error={err?.message}
|
||||
removeError={() => setErr(undefined)}
|
||||
/>
|
||||
<ChessBoard
|
||||
key={chess.getFEN()}
|
||||
chess={chess}
|
||||
makeMove={makeMove}
|
||||
blackPerspective={color === COLOR.BLACK}
|
||||
disabled={color != chess.getTurn()}
|
||||
disabled={color !== chess.getTurn()}
|
||||
/>
|
||||
</Show>
|
||||
);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { useState } from "react";
|
||||
import { useLocation, useNavigate } from "react-router-dom";
|
||||
import { Color, COLOR } from "../../../server/src/engine";
|
||||
import Show from "../utils/Show";
|
||||
import { CircleExclamation } from "../utils/icons";
|
||||
import ErrorNorification from "../utils/ErrorNotification";
|
||||
|
||||
const Home = () => {
|
||||
const navigate = useNavigate();
|
||||
@@ -66,10 +66,7 @@ const Home = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Err
|
||||
key={errObj.error}
|
||||
{...errObj}
|
||||
/>
|
||||
<ErrorNorification key={errObj.error} {...errObj} />
|
||||
<div className="text-xl">
|
||||
<div className="absolute top-0 left-0 right-0 bottom-0 m-auto p-6 bg-gray-800 text-white w-fit h-fit rounded-[25px]">
|
||||
<button
|
||||
@@ -148,48 +145,4 @@ const Home = () => {
|
||||
);
|
||||
};
|
||||
|
||||
const Err: React.FC<{
|
||||
error?: string;
|
||||
removeError: () => void;
|
||||
}> = ({ error, removeError }) => {
|
||||
const [err, setErr] = useState(error);
|
||||
const divRef = useRef<HTMLDivElement | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const id = setTimeout(() => {
|
||||
let duration = 1;
|
||||
if (divRef.current != null) {
|
||||
divRef.current.classList.add(
|
||||
"opacity-0",
|
||||
"transition-opacity",
|
||||
"duration-300"
|
||||
);
|
||||
duration = 300;
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
removeError();
|
||||
setErr(undefined);
|
||||
console.log("Removed error");
|
||||
}, duration);
|
||||
}, 2 * 1000);
|
||||
|
||||
return () => clearTimeout(id);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Show when={err != undefined}>
|
||||
<div
|
||||
ref={divRef}
|
||||
className="flex justify-center items-center gap-1 w-fit mt-2 mr-4 ml-auto border border-black p-2 rounded-md text-lg"
|
||||
>
|
||||
<span className="text-red-700">
|
||||
<CircleExclamation />
|
||||
</span>
|
||||
{err}
|
||||
</div>
|
||||
</Show>
|
||||
);
|
||||
};
|
||||
|
||||
export default Home;
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import Show from "./Show";
|
||||
import { CircleExclamation } from "./icons";
|
||||
|
||||
const ErrorNorification: React.FC<{
|
||||
error?: string;
|
||||
removeError: () => void;
|
||||
}> = ({ error, removeError }) => {
|
||||
const [err, setErr] = useState(error);
|
||||
const divRef = useRef<HTMLDivElement | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
const id = setTimeout(() => {
|
||||
if (err == undefined) return;
|
||||
|
||||
let duration = 1;
|
||||
if (divRef.current != null) {
|
||||
divRef.current.classList.add(
|
||||
"opacity-0",
|
||||
"transition-opacity",
|
||||
"duration-300"
|
||||
);
|
||||
duration = 300;
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
removeError();
|
||||
setErr(undefined);
|
||||
console.log("Removed error");
|
||||
}, duration);
|
||||
}, 2 * 1000);
|
||||
|
||||
return () => clearTimeout(id);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<Show when={err != undefined}>
|
||||
<div
|
||||
ref={divRef}
|
||||
className="absolute top-0 right-0 flex justify-center items-center gap-1 w-fit mt-2 mr-4 border border-black p-2 rounded-md text-lg"
|
||||
>
|
||||
<span className="text-red-700">
|
||||
<CircleExclamation />
|
||||
</span>
|
||||
{err}
|
||||
</div>
|
||||
</Show>
|
||||
);
|
||||
};
|
||||
|
||||
export default ErrorNorification;
|
||||
@@ -821,7 +821,7 @@ export default class Chess {
|
||||
}
|
||||
|
||||
if (moveObj == null)
|
||||
throw new Error(`Move ${JSON.stringify(move)} not found`);
|
||||
throw new Error("Move not found");
|
||||
|
||||
this._makeMove(moveObj);
|
||||
}
|
||||
|
||||
+15
-1
@@ -68,7 +68,21 @@ io.on("connection", (socket) => {
|
||||
});
|
||||
|
||||
socket.on("make move", (id: string, move: Move) => {
|
||||
socket.to(id).emit("receive move", move);
|
||||
const room = rooms.get(id);
|
||||
|
||||
if (room == undefined) return socket.emit("move error", "Invalid game ID");
|
||||
|
||||
const chess = room.game;
|
||||
|
||||
if (socket.id != room[chess.getTurn()])
|
||||
return socket.emit("move error", "Not your turn!");
|
||||
|
||||
try {
|
||||
chess.makeMove(move);
|
||||
io.to(id).emit("receive move", move);
|
||||
} catch (e) {
|
||||
socket.emit("move error", (e as Error).message);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user