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
+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
)