fix(chess): prevent duplicate players and fix move detection
Some checks failed
Deploy to Production / test (push) Failing after 38s
Some checks failed
Deploy to Production / test (push) Failing after 38s
- Prevent same player from joining as both white and black - Add validation to reject duplicate players in RoomManager - Fix spectator status not resetting when joining as player - Use ref to track latest chess state in ChessBoard for accurate move validation
This commit is contained in:
@@ -46,7 +46,8 @@ export class RoomManager {
|
||||
|
||||
const plugin = gameRegistry.get(room.gameSlug)!;
|
||||
if (room.players.length >= plugin.maxPlayers && role !== "admin") return { ok: false, error: "Room is full" };
|
||||
if (room.players.includes(playerId) && role !== "admin") return { ok: true, started: room.status === "playing" };
|
||||
if (room.players.includes(playerId) && role !== "admin") return { ok: true, started: room.status === "waiting" };
|
||||
if (room.players.includes(playerId) && role === "admin") return { ok: false, error: "Already a player in this game" };
|
||||
|
||||
if (!room.players.includes(playerId) || role === "admin") {
|
||||
room.players.push(playerId);
|
||||
|
||||
@@ -18,6 +18,12 @@ export function ChessBoard({ state, myPlayerId, isSpectator, onAction, players }
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
const [boardWidth, setBoardWidth] = useState(400);
|
||||
|
||||
// Track latest state in ref to avoid stale closures
|
||||
const chessRef = useRef(chess);
|
||||
useEffect(() => {
|
||||
chessRef.current = chess;
|
||||
}, [chess]);
|
||||
|
||||
// Responsive board sizing
|
||||
useEffect(() => {
|
||||
const container = containerRef.current;
|
||||
@@ -56,7 +62,7 @@ export function ChessBoard({ state, myPlayerId, isSpectator, onAction, players }
|
||||
function onDrop(sourceSquare: string, targetSquare: string): boolean {
|
||||
if (isSpectator || !isMyTurn) return false;
|
||||
|
||||
const testGame = new Chess(chess.fen);
|
||||
const testGame = new Chess(chessRef.current.fen);
|
||||
|
||||
// Check if this is a promotion move
|
||||
const piece = testGame.get(sourceSquare as any);
|
||||
|
||||
@@ -56,13 +56,16 @@ export function useGameRoom(roomId: string, userId: string, role?: string) {
|
||||
return {
|
||||
...prev,
|
||||
spectators: [...prev.spectators.filter(s => s.discordId !== msg.player.discordId), msg.player],
|
||||
isSpectator: isMe ? true : prev.isSpectator,
|
||||
isSpectator: isMe || prev.isSpectator,
|
||||
roomStatus: prev.roomStatus === "connecting" ? "waiting" : prev.roomStatus,
|
||||
};
|
||||
}
|
||||
|
||||
const isMe = msg.player.discordId === userId;
|
||||
return {
|
||||
...prev,
|
||||
players: [...prev.players.filter(p => p.discordId !== msg.player.discordId), msg.player],
|
||||
isSpectator: isMe ? false : prev.isSpectator,
|
||||
roomStatus: prev.roomStatus === "connecting" ? "waiting" : prev.roomStatus,
|
||||
};
|
||||
});
|
||||
|
||||
@@ -23,9 +23,14 @@ export const chessPlugin: GamePlugin<ChessState, ChessAction> = {
|
||||
|
||||
createInitialState(players: string[]): ChessState {
|
||||
const game = new Chess();
|
||||
|
||||
if (players[0] === players[1]) {
|
||||
throw new Error("Cannot create chess game with same player for both sides");
|
||||
}
|
||||
|
||||
return {
|
||||
fen: game.fen(),
|
||||
players: { white: players[0], black: players[1] },
|
||||
players: { white: players[0]!, black: players[1]! },
|
||||
moveHistory: [],
|
||||
status: "playing",
|
||||
winner: null,
|
||||
|
||||
Reference in New Issue
Block a user