discord login

This commit is contained in:
2024-05-07 23:09:52 +02:00
parent 082e07c48b
commit ade051890e
15 changed files with 317 additions and 145 deletions
+2 -1
View File
@@ -9,7 +9,8 @@
"type": "debugpy",
"request": "launch",
"program": "src/main.py",
"console": "internalConsole"
"console": "internalConsole",
"envFile": "${workspaceFolder}/.env"
}
]
}
+3
View File
@@ -0,0 +1,3 @@
{
"mypy-type-checker.reportingScope": "workspace"
}
+7
View File
@@ -1,11 +1,18 @@
annotated-types==0.6.0
certifi==2024.2.2
charset-normalizer==3.3.2
gevent==24.2.1
greenlet==3.0.3
idna==3.7
mypy==1.9.0
mypy-extensions==1.0.0
pydantic==2.6.4
pydantic_core==2.16.3
requests==2.31.0
setuptools==69.5.1
types-requests==2.31.0.20240406
typing_extensions==4.10.0
urllib3==2.2.1
websockets==12.0
zope.event==5.0
zope.interface==6.2
+36
View File
@@ -0,0 +1,36 @@
import requests
import os
def discord_process_code(code: str) -> dict | None:
response = requests.post(
url="https://discord.com/api/oauth2/token",
headers={
"Content-Type": "application/x-www-form-urlencoded",
},
data={
"client_id": os.environ["DISCORD_CLIENTID"],
"client_secret": os.environ["DISCORD_CLIENTSECRET"],
"code": code,
"grant_type": "authorization_code",
"redirect_uri": os.environ["FRONTEND_ENDPOINT"] + "/login",
"scope": "identify",
},
timeout=10,
)
json_data = response.json()
if "error" in json_data:
print(json_data)
return None
token_type = json_data["token_type"]
access_token = json_data["access_token"]
response = requests.get(
url="https://discord.com/api/users/@me",
headers={
"authorization": token_type + " " + access_token,
},
timeout=10,
)
return response.json()
+134 -76
View File
@@ -4,11 +4,14 @@ from typing import Callable, Any, TYPE_CHECKING
from pydantic import ValidationError
from websockets.server import WebSocketServerProtocol
from websockets.exceptions import ConnectionClosedOK
from netcode.models import Message, LoginMessage
from netcode.models import Message, LoginMessage, MessageType
from model import Player
from .auth import discord_process_code
if TYPE_CHECKING:
from controller import GameController
@@ -55,7 +58,7 @@ class ClientController:
"""Hooks the client to the correct listen callbacks"""
await self.send(
Message(
type="context",
type=MessageType.CONTEXT,
data_type="game_context_id",
data="login",
)
@@ -68,15 +71,18 @@ class ClientController:
async def send(self, message: Message) -> None:
"""Send a Message object to the connected client"""
await self.websocket.send(message.model_dump_json())
try:
await self.websocket.send(message.model_dump_json())
except ConnectionClosedOK:
print("Connection Closed")
async def send_error(self, error: str) -> None:
"""Send an error string to the connected client"""
await self.send(Message(type="error", data_type="error", data=error))
await self.send(Message(type=MessageType.ERROR, data_type="error", data=error))
async def send_announce_dict(
self,
notification_type: str,
notification_type: MessageType,
data: dict,
player_filter: Callable[[Player], Any] = lambda x: True,
):
@@ -89,65 +95,15 @@ class ClientController:
Message(type=notification_type, data_type="object", data=data)
)
@vibe_check(Message)
async def game_context(self, message: Message) -> None:
"""Handles all messages related to when the current client is logged in
and connected to a running game"""
if message.type == "temp_action":
if message.data_type == "set_health":
self.player.team.health = message.data
return await self.game_controller.game.notify_controller(
"update", self.player.team.serialize_guest()
)
if self.player.team != self.game_controller.game.current_turn:
return await self.send_error("it is not your turn to play!")
if message.type == "action":
# TODO : pydantic type check for message.data
match message.data_type:
case "play_card":
return await self.player.play_card(message.data)
case "discard":
return await self.player.turn.discard_card(message.data)
case "lock_card":
return await self.player.turn.lock_card(message.data)
case "use_effect":
return await self.player.turn.use_effect_with_check(
message.data.get("effect_id"), message.data.get("target")
)
case "buy":
return await self.player.turn.buy_card(message.data)
case "heal":
return await self.player.turn.heal(message.data)
case "damage_team":
return await self.player.turn.damage_team(message.data)
case "damage_champion":
return await self.player.turn.damage_champion(message.data)
case "end_turn":
return await self.player.turn.end_turn()
return await self.send_error(
"Couldn't process action with data_type : " + message.data_type
)
@vibe_check(LoginMessage)
async def login_context(self, message: LoginMessage) -> None:
"""Handles all messages related to when the current client isn't yet logged in"""
username = message.data
if self.game_controller.game.started:
return await self.send_error(
"you cannot interact with a game that has already started"
)
if message.type == "register":
if message.type == MessageType.REGISTER:
if self.game_controller.game.started:
return await self.send_error(
"you cannot interact with a game that has already started"
)
if len(username) < 3:
return await self.send_error(
"username must be longer than 3 characters"
@@ -157,36 +113,81 @@ class ClientController:
return await self.send_error("username already exists")
player = await self.game_controller.game.create_player(username)
elif message.type == "login":
elif message.type == MessageType.LOGIN:
player2 = self.game_controller.game.get_player(username)
if player2 is None:
return await self.send_error("player doesn't exists")
player = player2
elif message.type == MessageType.DISCORD_LOGIN:
user = discord_process_code(message.data)
if user is None:
await self.send_error("discord login not successful")
return
username = user["global_name"]
player = next(
(
p
for p in self.game_controller.game.players
if p.discord_id == user["id"]
),
None,
)
if player is None:
if self.game_controller.game.started:
return await self.send_error(
"you cannot interact with a game that has already started"
)
player = await self.game_controller.game.create_player(username)
player.discord_id = user["id"]
player.image = (
"https://cdn.discordapp.com/avatars/"
+ user["id"]
+ "/"
+ user["avatar"]
+ ".webp"
)
else:
return await self.send_error("invalid message type for context")
self.player = player
self.player.team.listeners.append(self.send_announce_dict)
self.on_message = self.pregame_context
if self.game_controller.game.started:
self.on_message = self.game_context
await self.send(
Message(
type=MessageType.CONTEXT, data_type="game_context_id", data="game"
)
)
for p in self.game_controller.game.players:
if p.team == player.team:
await self.send(
Message(
type=MessageType.UPDATE,
data_type="object",
data=player.serialize_team(),
)
)
else:
self.on_message = self.pregame_context
await self.send(
Message(
type=MessageType.CONTEXT,
data_type="game_context_id",
data="pregame",
)
)
print("user logged in : " + username)
await self.send(
Message(
type="set",
type=MessageType.SET,
data_type="self",
data=self.player.uuid,
)
)
await self.send(
Message(
type="context",
data_type="game_context_id",
data="pregame",
)
)
@vibe_check(Message)
async def pregame_context(self, message: Message) -> None:
@@ -197,9 +198,66 @@ class ClientController:
if all(p.ready for p in self.game_controller.game.players):
await self.game_controller.start_game()
elif message.type == "temp_action":
if message.data_type == "set_health":
self.player.team.health = message.data
await self.game_controller.game.notify_controller(
"update", self.player.team.serialize_guest()
)
@vibe_check(Message)
async def game_context(self, message: Message) -> None:
"""Handles all messages related to when the current client is logged in
and connected to a running game"""
# if message.type == "temp_action":
# if message.data_type == "set_health":
# self.player.team.health = message.data
# return await self.game_controller.game.notify_controller(
# "update", self.player.team.serialize_guest()
# )
if self.player.team != self.game_controller.game.current_turn:
return await self.send_error("it is not your turn to play!")
if message.type == "action":
# TODO : pydantic type check for message.data
match message.data_type:
case "play_card":
if not isinstance(message.data, str):
return
return await self.player.play_card(message.data)
case "discard":
if not isinstance(message.data, str):
return
return await self.player.turn.discard_card(message.data)
case "lock_card":
if not isinstance(message.data, str):
return
return await self.player.turn.lock_card(message.data)
case "use_effect":
return await self.player.turn.use_effect_with_check(
message.data.get("effect_id"), message.data.get("target")
)
case "buy":
if not isinstance(message.data, str):
return
return await self.player.turn.buy_card(message.data)
case "heal":
if not isinstance(message.data, int):
return
return await self.player.turn.heal(message.data)
case "damage_team":
if not isinstance(message.data, str):
return
return await self.player.turn.damage_team(message.data)
case "damage_champion":
if not isinstance(message.data, str):
return
return await self.player.turn.damage_champion(message.data)
case "end_turn":
return await self.player.turn.end_turn()
return await self.send_error(
"Couldn't process action with data_type : " + message.data_type
)
+15 -11
View File
@@ -1,8 +1,9 @@
import asyncio
from typing import Callable, List, Any
from websockets.exceptions import ConnectionClosedOK
from netcode import WSServer
from netcode.ws_server import WebSocketServerProtocol
from netcode.models import Message
from netcode.models import Message, MessageType
from model import Game, Player
from controller import (
ClientController,
@@ -31,14 +32,17 @@ class GameController:
self.clients.remove(client)
async def send(self, message: Message, websocket: WebSocketServerProtocol):
await websocket.send(message.model_dump_json())
try:
await websocket.send(message.model_dump_json())
except ConnectionClosedOK:
print("Connection Closed")
async def broadcast(self, message: Message):
await self.server.broadcast(message.model_dump_json())
async def broadcast_announce_dict(
self,
notification_type: str,
notification_type: MessageType,
data: dict,
player_filter: Callable[[Player], Any],
):
@@ -58,7 +62,7 @@ class GameController:
async def announce_dict(
self,
notification_type: str,
notification_type: MessageType,
data: dict,
websocket: WebSocketServerProtocol,
):
@@ -74,39 +78,39 @@ class GameController:
async def announce_game(self, websocket: WebSocketServerProtocol):
for effect in self.game.effects:
await self.announce_dict(
"create",
MessageType.CREATE,
effect.serialize(),
websocket,
)
for card in self.game.cards:
await self.announce_dict(
"create",
MessageType.CREATE,
card.serialize(),
websocket,
)
for team in self.game.teams:
await self.announce_dict(
"create",
MessageType.CREATE,
team.serialize(),
websocket,
)
for player in self.game.players:
await self.announce_dict(
"create",
MessageType.CREATE,
player.turn.serialize(),
websocket,
)
await self.announce_dict(
"create",
MessageType.CREATE,
player.serialize_guest(),
websocket,
)
await self.announce_dict(
"create",
MessageType.CREATE,
self.game.serialize_guest(),
websocket,
)
@@ -119,5 +123,5 @@ class GameController:
for c in self.clients:
c.on_message = c.game_context
await self.broadcast(
Message(type="context", data_type="game_context_id", data="game")
Message(type=MessageType.CONTEXT, data_type="game_context_id", data="game")
)
+3 -3
View File
@@ -1,4 +1,4 @@
from typing import List, Optional, Callable, TYPE_CHECKING, Union
from typing import List, Optional, Callable, TYPE_CHECKING, Union, Awaitable, Any
from model import Serializable, CardRole, CardType, CardFaction
from model.card_validator import CardEffects, EffectType, EffectTimes
@@ -17,13 +17,13 @@ class Effect(Serializable):
effect_type: Optional[EffectType] = None
times: Optional[EffectTimes] = None
card: "Card"
activate: Callable[["Turn"], Union["Player", "Card"]]
activate: Callable[["Turn", str | None], Awaitable[Any]]
def __init__(
self,
effect: CardEffects,
amount: int,
activate: Callable[["Turn"], Union["Player", "Card"]],
activate: Callable[["Turn", str | None], Awaitable[Any]],
sub_effects: Optional[List["Effect"]] = None,
effect_type: Optional[EffectType] = None,
times: Optional[EffectTimes] = None,
+14 -9
View File
@@ -1,4 +1,4 @@
from typing import TYPE_CHECKING, Awaitable, Optional
from typing import TYPE_CHECKING, Optional, Callable, Coroutine, Any
from model.card_validator import EffectParser
from model.card import Effect, EffectType, CardEffects, EffectTimes, CardType
@@ -6,6 +6,8 @@ from model.card import Effect, EffectType, CardEffects, EffectTimes, CardType
if TYPE_CHECKING:
from model import Turn
# pylint: disable=unused-argument,missing-function-docstring
# Effect Types
async def effect_type_suicide(effect: Effect, turn: "Turn"):
@@ -55,19 +57,20 @@ async def effect_heal(effect: Effect, turn: "Turn", _target: str):
return True
async def effect_prepare(_effect: Effect, turn: "Turn", target: str):
async def effect_prepare(effect: Effect, turn: "Turn", target: str):
return turn.prepare(target)
async def effect_stun(_effect: Effect, turn: "Turn", target: str):
async def effect_stun(effect: Effect, turn: "Turn", target: str):
return await turn.player.stun(target)
async def effect_sacrifice(_effect: Effect, turn: "Turn", target: str):
async def effect_sacrifice(effect: Effect, turn: "Turn", target: str):
return await turn.sacrifice_card(target)
async def effect_draw(_effect: Effect, turn: "Turn", _target: str):
async def effect_draw(effect: Effect, turn: "Turn", _target: str):
return await turn.player.draw_and_play(1)
@@ -169,9 +172,11 @@ effect_times_all_behaviours = {
}
def create_effect_behaviour(effect: EffectParser) -> Awaitable[None]:
def create_effect_behaviour(
effect: EffectParser,
) -> Callable[[Effect, "Turn", str | None], Coroutine[Any, Any, Any]]:
async def effect_type_behaviour(e: Effect, t: "Turn"):
async def effect_type_behaviour(effect: Effect, turn: "Turn"):
return True
if effect.effect_type in effect_types_all_behaviours:
@@ -182,7 +187,7 @@ def create_effect_behaviour(effect: EffectParser) -> Awaitable[None]:
card_effect_behaviour = card_effect_all_behaviours[effect.effect]
def effect_times_behaviour(_e: Effect, _t: "Turn"):
def effect_times_behaviour(effect: Effect, turn: "Turn"):
return 1
if effect.times in effect_times_all_behaviours:
@@ -194,7 +199,7 @@ def create_effect_behaviour(effect: EffectParser) -> Awaitable[None]:
return False
times = effect_times_behaviour(self, turn)
for _ in range(times):
effect_result = await card_effect_behaviour(self, turn, target)
effect_result = await card_effect_behaviour(self, turn, (target or ""))
if not effect_result:
return False
return True
+22 -9
View File
@@ -1,5 +1,5 @@
from json import JSONDecodeError
from typing import List, Dict, Optional
from typing import List, Dict, Optional, TYPE_CHECKING, Union
from pathlib import Path
from pydantic import BaseModel, ValidationError
@@ -8,6 +8,9 @@ from model.card_validator import CardParser, EffectParser
from model.card import Effect, Card
from .card_behaviour import create_effect_behaviour
if TYPE_CHECKING:
from model import Turn, Player
class CardContainerFile(BaseModel):
cards: List[CardParser]
@@ -29,7 +32,7 @@ def load_cards() -> List[CardParser]:
return cards
def create_card(card_parser: CardParser) -> tuple[Card, list[Effect], list[Effect]]:
def create_card(card_parser: CardParser) -> tuple[Card, list[Effect]]:
card_effects, all_effects = create_card_effects(card_parser)
card = Card(
card_id=card_parser.id,
@@ -50,9 +53,14 @@ def create_card(card_parser: CardParser) -> tuple[Card, list[Effect], list[Effec
def create_card_effects(
card: CardParser, all_effects: Optional[List[Effect]] = None
) -> (List[Effect], List[Effect]):
) -> tuple[List[Effect], List[Effect]]:
if all_effects is None:
all_effects: List[Effect] = []
all_effects = []
if all_effects is None:
raise RuntimeError("shut up MyPy")
combined: List[Effect] = []
mutexes: Dict[int, List[Effect]] = {}
for mutex in set([c.mutex for c in card.effects if c.mutex is not None]):
@@ -76,9 +84,13 @@ def create_card_effects(
def create_effect_and_subeffects(
effect: EffectParser, all_effects: Optional[List[Effect]] = None
) -> (Effect, List[Effect]):
) -> tuple[Effect, List[Effect]]:
if all_effects is None:
all_effects: List[Effect] = []
all_effects = []
if all_effects is None:
raise RuntimeError("shut up MyPy")
sub_effects: List[Effect] = []
mutexes: Dict[int, List[Effect]] = {}
for mutex in set([c.mutex for c in effect.sub_effects if c.mutex is not None]):
@@ -97,15 +109,16 @@ def create_effect_and_subeffects(
if s.mutex in mutexes:
sub_effects[index].mutex = mutexes[s.mutex]
def activate(turn: "Turn", target: str | None):
return create_effect_behaviour(effect=effect)(actual_effect, turn, target)
actual_effect = Effect(
effect=effect.effect,
amount=effect.amount,
effect_type=effect.effect_type,
sub_effects=sub_effects,
times=effect.times,
activate=lambda *args, **kwargs: create_effect_behaviour(effect=effect)(
actual_effect, *args, **kwargs
),
activate=activate,
)
return actual_effect, all_effects
+11 -9
View File
@@ -7,6 +7,8 @@ from model import Card, CardRole, CardParser, Player, Team, Serializable, Effect
from model.card_loader import load_cards, create_card_effects, create_card
from netcode.models import MessageType
class Game(Serializable):
"""Instance of the game, with players and a market"""
@@ -17,7 +19,7 @@ class Game(Serializable):
cards: List[Card]
effects: List[Effect]
market_stack: List[Card]
market: List[Card]
market: List[Card | None]
gem_stack: List[Card]
players: List[Player]
teams: List[Team]
@@ -26,7 +28,7 @@ class Game(Serializable):
default_health = 50
current_turn: Team
current_turn: Team | None
def __init__(self) -> None:
super().__init__()
@@ -50,10 +52,10 @@ class Game(Serializable):
card, all_effects = create_card(card_parser)
for e in all_effects:
self.effects.append(e)
await self.notify_controller("create", e.serialize())
await self.notify_controller(MessageType.CREATE, e.serialize())
self.cards.append(card)
await self.notify_controller("create", card.serialize())
await self.notify_controller(MessageType.CREATE, card.serialize())
return card
async def init_cards(self):
@@ -91,15 +93,15 @@ class Game(Serializable):
self.players.append(player)
player.stack_pile = await self.create_base_deck("base")
await self.notify_controller("create", player.turn.serialize())
await self.notify_controller("create", player.serialize_guest())
await self.notify_controller("update", self.serialize_guest())
await self.notify_controller(MessageType.CREATE, player.turn.serialize())
await self.notify_controller(MessageType.CREATE, player.serialize_guest())
await self.notify_controller(MessageType.UPDATE, self.serialize_guest())
return player
async def create_team(self) -> Team:
team = Team(health=self.default_health)
self.teams.append(team)
await self.notify_controller("create", team.serialize_guest())
await self.notify_controller(MessageType.CREATE, team.serialize_guest())
return team
@@ -169,7 +171,7 @@ class Game(Serializable):
await p.start_turn()
await self.notify_controller("update", self.serialize_guest())
def search_card_in_pile(self, card_id: str, pile: List[Card]):
def search_card_in_pile(self, card_id: str, pile: list[Card | None] | list[Card]):
return next(
(m for m in [f for f in pile if f is not None] if str(m.uuid) == card_id),
None,
+19 -7
View File
@@ -6,6 +6,8 @@ from typing import List, Optional, TYPE_CHECKING
from model import Card, Team, Serializable, Turn, CardType, CardRole
from netcode.models import MessageType
if TYPE_CHECKING:
from model import Game
@@ -15,6 +17,8 @@ class Player(Serializable):
object_type = "player"
username: str
image: Optional[str] = None
discord_id: Optional[int] = None
stack_pile: List[Card]
discard_pile: List[Card]
@@ -110,7 +114,7 @@ class Player(Serializable):
await asyncio.gather(*notifies)
def source_card(self, card_id: str, source: List[Card]) -> Card:
def source_card(self, card_id: str, source: List[Card]) -> Card | None:
card = self.game.search_card_in_pile(card_id, source)
if card is None:
return None
@@ -184,7 +188,9 @@ class Player(Serializable):
return False
self.discard_pile.append(card)
await self.game.notify_controller("update", self.game.serialize_guest())
await self.game.notify_controller(
MessageType.UPDATE, self.game.serialize_guest()
)
await self.notify_update()
return True
@@ -199,7 +205,9 @@ class Player(Serializable):
if card.card_role == CardRole.FIRE_GEM:
self.game.gem_stack.append(card)
await self.notify_update()
await self.game.notify_controller("update", self.game.serialize_guest())
await self.game.notify_controller(
MessageType.UPDATE, self.game.serialize_guest()
)
return True
async def play_from_discard(self, card_id: str):
@@ -220,7 +228,7 @@ class Player(Serializable):
self.stack_pile.append(card)
else:
print("Card not found in discard pile")
return
return False
await self.notify_update()
return True
@@ -237,7 +245,9 @@ class Player(Serializable):
return False
self.board.append(card)
await self.game.notify_controller("update", self.game.serialize_guest())
await self.game.notify_controller(
MessageType.UPDATE, self.game.serialize_guest()
)
await self.notify_update()
return True
@@ -253,7 +263,9 @@ class Player(Serializable):
return False
self.stack_pile.append(card)
await self.game.notify_controller("update", self.game.serialize_guest())
await self.game.notify_controller(
MessageType.UPDATE, self.game.serialize_guest()
)
await self.notify_update()
return True
@@ -286,5 +298,5 @@ class Player(Serializable):
print("player has already too many discard markers!")
return False
p.turn.fuck_u_markers += 1
await self.game.notify_controller("update", p.turn.serialize())
await self.game.notify_controller(MessageType.UPDATE, p.turn.serialize())
return True
+4 -2
View File
@@ -1,13 +1,15 @@
from typing import List, Callable, Awaitable, Any
from uuid import uuid4, UUID
from netcode.models import MessageType
class Serializable:
object_type = "serializable"
uuid: UUID
listeners: List[Callable[[str, dict, Callable], Awaitable[Any]]]
listeners: List[Callable[[MessageType, dict, Callable], Awaitable[Any]]]
def __init__(self) -> None:
self.uuid = uuid4()
@@ -24,7 +26,7 @@ class Serializable:
async def notify_controller(
self,
notification_type: str,
notification_type: MessageType,
game_object: dict,
# TODO : Player interface to typing
player_filter: Callable[[Any], bool] = lambda _: True,
+20 -11
View File
@@ -13,6 +13,7 @@ from model import (
Team,
)
from netcode.models import MessageType
if TYPE_CHECKING:
from model import Player
@@ -64,9 +65,9 @@ class Turn(Serializable):
for p in self.player.game.players:
p.turn.champions_health = {}
for c in p.board:
if c.card_type == CardType.CHAMPION:
if c.card_type == CardType.CHAMPION and c.defense is not None:
p.turn.champions_health[str(c.uuid)] = c.defense
await p.game.notify_controller("update", p.turn.serialize())
await p.game.notify_controller(MessageType.UPDATE, p.turn.serialize())
await self.player.end_turn()
@@ -98,7 +99,7 @@ class Turn(Serializable):
for _ in range(effect.amount):
self.effects_availables.append(effect)
await self.player.game.notify_controller("update", self.serialize())
await self.player.game.notify_controller(MessageType.UPDATE, self.serialize())
async def discard_card(self, card_id: str):
card = self.player.game.search_card_in_pile(card_id, self.cards_locked)
@@ -113,7 +114,7 @@ class Turn(Serializable):
return print("you don't have any discard or fuck_u markers")
await self.player.discard_card(card_id)
await self.player.game.notify_controller("update", self.serialize())
await self.player.game.notify_controller(MessageType.UPDATE, self.serialize())
def sacrifice_card(self, card_id: str):
card = self.player.game.search_card_in_pile(card_id, self.cards_locked)
@@ -168,7 +169,7 @@ class Turn(Serializable):
else:
for _ in range(e.amount):
self.effects_availables.append(e)
await self.player.game.notify_controller("update", self.serialize())
await self.player.game.notify_controller(MessageType.UPDATE, self.serialize())
def prepare(self, card_id: str) -> bool:
card = next(
@@ -243,14 +244,18 @@ class Turn(Serializable):
if await buy_function(card):
self.gold_reserve -= card.cost
await self.player.game.notify_controller("update", self.serialize())
await self.player.game.notify_controller(
MessageType.UPDATE, self.serialize()
)
return True
return False
async def heal(self, amount: int):
self.player.team.health += amount
await self.player.game.notify_controller("update", self.player.team.serialize())
await self.player.game.notify_controller(
MessageType.UPDATE, self.player.team.serialize()
)
def check_for_guard(self, team: "Team"):
for p in self.player.game.players:
@@ -277,8 +282,8 @@ class Turn(Serializable):
self.damage_reserve -= 1
team.health -= 1
await self.player.game.notify_controller("update", self.serialize())
await self.player.game.notify_controller("update", team.serialize())
await self.player.game.notify_controller(MessageType.UPDATE, self.serialize())
await self.player.game.notify_controller(MessageType.UPDATE, team.serialize())
async def damage_champion(self, target: str):
if self.damage_reserve <= 0:
@@ -301,8 +306,12 @@ class Turn(Serializable):
self.damage_reserve -= p.turn.champions_health[str(c.uuid)]
await self.player.stun(str(c.uuid))
await self.player.game.notify_controller("update", self.serialize())
await self.player.game.notify_controller("update", p.turn.serialize())
await self.player.game.notify_controller(
MessageType.UPDATE, self.serialize()
)
await self.player.game.notify_controller(
MessageType.UPDATE, p.turn.serialize()
)
return
print("card not found")
+24 -2
View File
@@ -1,9 +1,31 @@
from typing import Any
from enum import Enum
from typing import Any, Literal
from pydantic import BaseModel
class MessageType(str, Enum):
ACTION = "action"
REGISTER = "register"
LOGIN = "login"
READY = "ready"
DISCORD_LOGIN = "discord_login"
CONTEXT = "context"
CREATE = "create"
ERROR = "error"
UPDATE = "update"
SET = "set"
class CreateMessageType(BaseModel):
type: Literal[MessageType.CREATE]
data_type: "object"
data: dict
class Message(BaseModel):
type: str
type: MessageType
data: Any | str | int | None = None
data_type: str
+3 -5
View File
@@ -9,20 +9,21 @@ class WSServer:
connections: Set[WebSocketServerProtocol]
on_new_connection_callback: Callable[
[WebSocketServerProtocol, Callable[[Any], Awaitable[None]]], Awaitable[None]
[WebSocketServerProtocol, Callable[[], Any]], Awaitable[None]
]
port: int
def __init__(self) -> None:
self.connections = set()
self.message_callbacks = []
self.message_callbacks: list[Callable] = []
async def handler(self, websocket: WebSocketServerProtocol):
"""Is called everytime a client connects to the websocket"""
self.connections.add(websocket)
async def track_connection():
"""Keeps track of connected clients in the connections property"""
try:
await websocket.wait_closed()
finally:
@@ -30,9 +31,6 @@ class WSServer:
await self.on_new_connection_callback(websocket, track_connection)
async def track_connection(self, websocket: WebSocketServerProtocol):
"""Keeps track of connected clients in the connections property"""
async def serve(self, address="0.0.0.0", port=8765):
"""Call to start the websocket"""