Skip to content

Commit

Permalink
Added Event Handler
Browse files Browse the repository at this point in the history
Handles different events and updates the game state accordingly

Also Integrated with GameProvider to handle these events

Fixes:#124
  • Loading branch information
Abhishek committed Jun 24, 2024
1 parent 1c913c3 commit 45a6b93
Show file tree
Hide file tree
Showing 2 changed files with 141 additions and 8 deletions.
127 changes: 127 additions & 0 deletions frontend/src/clientDispatch.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import { GameEvent, GameEventTypes } from '../../backend/src/types';
import { GameState } from './contexts/GameContext';
import assert from 'assert';

export const clientDispatch = (
gameState: GameState,
event: GameEvent
): GameState => {
let newGameState: GameState;

switch (event.type) {
case GameEventTypes.JOIN_GAME:
newGameState = handleJoinGame(gameState, event);
break;
case GameEventTypes.LEAVE_GAME:
newGameState = handleLeaveGame(gameState, event);
break;
case GameEventTypes.DRAW_CARD:
newGameState = handleDrawCard(gameState, event);
break;
case GameEventTypes.THROW_CARD:
newGameState = handleThrowCard(gameState, event);
break;
case GameEventTypes.STATE_SYNC:
newGameState = handleStateSync(gameState, event);
break;
default:
throw new Error(`Unhandled event type: ${event}`);
}
return newGameState;
};

const handleJoinGame = (gameState: GameState, event: GameEvent): GameState => {
if (event.type !== GameEventTypes.JOIN_GAME) {
throw new Error(`Invalid event type for handleJoinGame: ${event.type}`);
}
assert(event.data !== undefined, 'Unknown Player');
const { playerId, data } = event;
const playerName = data.joinedPlayer.name;

return {
...gameState,
players: [
...gameState.players,
{ id: playerId, name: playerName, cards: [] },
],
};
};
const handleLeaveGame = (gameState: GameState, event: GameEvent): GameState => {
if (event.type !== GameEventTypes.LEAVE_GAME) {
throw new Error(
`Invalid event type for handleLeaveGame: ${event.type}`
);
}
const { playerId } = event;
return {
...gameState,
players: gameState.players.filter((player) => player.id !== playerId),
};
};

const handleDrawCard = (gameState: GameState, event: GameEvent): GameState => {
if (event.type !== GameEventTypes.DRAW_CARD) {
throw new Error(`Invalid event type for handleDrawCard: ${event.type}`);
}
const { playerId } = event;

// Find the player who drew the card
const updatedPlayers = gameState.players.map((player) => {
if (player.id === playerId) {
const updatedCards = [...player.cards];
return { ...player, cards: updatedCards };
}
return player;
});

return {
...gameState,
players: updatedPlayers,
};
};

const handleThrowCard = (gameState: GameState, event: GameEvent): GameState => {
if (event.type !== GameEventTypes.THROW_CARD) {
throw new Error(
`Invalid event type for handleThrowCard: ${event.type}`
);
}
const { playerId } = event;
const { cardId } = event.data;
return {
...gameState,
players: gameState.players.map((player) =>
player.id === playerId
? { ...player, cards: player.cards.filter((c) => c !== cardId) }
: player
),
lastThrownCard:
gameState.cardDeck.find((card) => card.id === cardId) || null,
};
};

const handleStateSync = (gameState: GameState, event: GameEvent): GameState => {
if (event.type !== GameEventTypes.STATE_SYNC) {
throw new Error(
`Invalid event type for handleStateSync: ${event.type}`
);
}
const { data } = event;
const mappedPlayers = data.players.map((player) => ({
id: player.id,
name: player.name,
cards: player.cards,
}));

return {
...gameState,
players: mappedPlayers,
cardDeck: data.cardDeck,
thrownCards: data.thrownCards,
currentPlayerIndex: data.currentPlayerIndex,
lastThrownCard: data.lastThrownCard,
direction: data.direction,
status: data.status,
runningEvents: data.runningEvents,
};
};
22 changes: 14 additions & 8 deletions frontend/src/contexts/GameContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,18 @@ import { useLocation, useNavigate } from 'react-router-dom';
import { useAuth } from './AuthContext';
import { useToast } from '../library/toast/toast-context';
import * as channel from '../channel';
import { clientDispatch } from '../clientDispatch';
import {
APIPlayer,
GameStatus,
RunningEvents,
UNOCard,
AppEvent,
GameEvent,
GameEventTypes,
} from '../../../backend/src/types';

interface GameState {
export interface GameState {
id: string;
cardDeck: UNOCard[];
thrownCards: UNOCard[];
Expand Down Expand Up @@ -56,7 +60,14 @@ export const GameProvider = () => {
const toast = useToast();
const auth = useAuth();
const backendUrl = process.env.REACT_APP_BACKEND_URL;

const dispatchGameEvent = (event: AppEvent) => {
if (event.type in GameEventTypes) {
setGameState((prevState) =>
clientDispatch(prevState as GameState, event as GameEvent)
);
}
// Handle ChatEvents
};
useEffect(() => {
if (!auth.isLoggedIn()) {
navigate('/login' + location.search);
Expand Down Expand Up @@ -125,12 +136,7 @@ export const GameProvider = () => {
useEffect(() => {
// add event listener to listen for the game state changes
channel.setGameEventsDispatcher((event) => {
// todo: this callback will be replaced by the event dispatcher
console.log('Handling event:', event);
if (event.type === 'STATE_SYNC') {
console.log(event.data);
setGameState(event.data);
}
dispatchGameEvent(event);
});
}, [gameState]);

Expand Down

0 comments on commit 45a6b93

Please sign in to comment.