import asyncio import logging from typing import Optional import websockets.exceptions from swiftstory.game import Game from swiftstory.exception import WrongAction, UnsupportedLanguage, JoinError class Client: def __init__(self, socket, game_manager): self.game: Optional[Game] = None self.game_manager = game_manager self.socket = socket self.player = None def join_game(self, game_name, lang): if self.game is not None: raise WrongAction('You are already in a game') if lang is None: lang = 'en' try: game = self.game_manager.join_game(game_name, lang) except UnsupportedLanguage as e: raise JoinError(f"unsupported language: {str(e)}") from e # XXX self.game will be assigned by game.try_join() return game.try_join(self) def play_white_card(self, card_id): if self.game is None: raise WrongAction('You have to join a game first') return self.game.try_play_card(self.player, card_id) def pick_black_card(self): if self.game is None: raise WrongAction('You have to join a game first') return self.game.try_become_judge(self.player) def collect_cards(self): if self.game is None: raise WrongAction('You have to join a game first') return self.game.try_collect_cards(self.player) def designate_card(self, card_id): if self.game is None: raise WrongAction('You have to join a game first') return self.game.try_designate_card(self.player, card_id) def view_player_cards(self): if self.game is None: raise WrongAction('You have to join a game first') return self.game.try_view_player_cards(self.player) def view_played_cards(self): if self.game is None: raise WrongAction('You have to join a game first') return self.game.try_view_played_cards(self.player) def view_black_card(self): if self.game is None: raise WrongAction('You have to join a game first') return self.game.try_view_black_card(self.player) def register_notification(self, message): async def f(): try: await self.socket.send(message) except websockets.exceptions.ConnectionClosed: logging.warning("Recipient has disconnected.") asyncio.create_task(f()) def disconnect(self): if self.player is not None: if self.game is None: raise ValueError("Disconnect from inexistent game.") self.game.disconnect(self.player)