player creation and broadcast

This commit is contained in:
2024-03-27 22:52:05 +01:00
parent 34c519345e
commit bac5f6e205
10 changed files with 94 additions and 37 deletions
+16 -8
View File
@@ -1,8 +1,9 @@
from pydantic import ValidationError
from controller import GameController
from websockets.server import WebSocketServerProtocol
from netcode.models import Message, LoginMessage, MessageData
from controller import GameController
from netcode.models import Message, LoginMessage
from game import Player
@@ -40,7 +41,13 @@ class ClientController:
async def listen(self):
"""Initializes the client controller"""
await self.send(Message(type="context", data=MessageData(message="login")))
await self.send(
Message(
type="context",
data_type="game_context_id",
data="login",
)
)
async for message in self.websocket:
await self.on_message(message)
@@ -49,7 +56,7 @@ class ClientController:
await self.websocket.send(message.model_dump_json())
async def send_error(self, error: str):
await self.send(Message(type="error", data=MessageData(message=error)))
await self.send(Message(type="error", data_type="error", data=error))
@vibe_check(Message)
async def game_context(self, message: Message):
@@ -59,8 +66,8 @@ class ClientController:
@vibe_check(LoginMessage)
async def login_context(self, message: LoginMessage):
"""Handles messages when the client isn't logged in"""
username = message.data
if message.type == "register":
username = message.data.username
if len(username) < 3:
await self.send_error("username must be longer than 3 characters")
@@ -70,9 +77,8 @@ class ClientController:
await self.send_error("username already exists")
return
player = self.game_controller.create_player(username)
player = await self.game_controller.create_player(username)
elif message.type == "login":
username = message.data.username
player = self.game_controller.get_player(username)
if player is None:
@@ -86,4 +92,6 @@ class ClientController:
self.player = player
self.on_message = self.game_context
print("user logged in : " + username)
await self.send(Message(type="context", data=MessageData(message="game")))
await self.send(
Message(type="context", data_type="game_context_id", data="game")
)
+27 -5
View File
@@ -1,6 +1,7 @@
from typing import Optional
import json
from netcode import WSServer
from game import Game, Player
from netcode.models import Message
from game import Game, Player, Team
class GameController:
@@ -11,14 +12,35 @@ class GameController:
self.server = server
self.game = game
def get_player(self, username: str) -> Optional[Player]:
async def broadcast(self, message: Message):
await self.server.broadcast(message.model_dump_json())
def get_player(self, username: str) -> Player | None:
players = [p for p in self.game.players if p.username == username]
if players and len(players) > 0:
return players[0]
return None
def create_player(self, username: str) -> Player:
return self.game.create_player(username)
async def create_player(self, username: str, team: Team | None = None) -> Player:
if team is None:
team = await self.create_team()
player = self.game.create_player(username, team)
await self.broadcast(
Message(
type="create",
data_type="player",
data=player.serialize_limited(),
)
)
return player
async def create_team(self):
team = self.game.create_team()
await self.broadcast(
Message(type="create", data_type="team", data=team.serialize())
)
return team
def start_game(self):
pass
+1
View File
@@ -1,3 +1,4 @@
from game.serializable import Serializable
from game.card import Card
from game.team import Team
from game.player import Player
+5 -1
View File
@@ -1,4 +1,5 @@
from enum import Enum
from game import Serializable
class CardType(str, Enum):
@@ -21,7 +22,7 @@ class CardFaction(str, Enum):
YELLOW = "yellow"
class Card:
class Card(Serializable):
"""Represents any playable card"""
sprite: str
@@ -34,6 +35,9 @@ class Card:
def __init__(self):
pass
def serialize(self) -> dict:
return self.__dict__
class CardChampion(Card):
"""Represents any champion card"""
+10 -4
View File
@@ -1,16 +1,16 @@
#!/usr/bin/env python
from typing import List
from game import Card, Player, Team
from game import Card, Player, Team, Serializable
class Game:
class Game(Serializable):
"""Instance of the game, with players and a market"""
market_stack: List[Card]
market: List[Card]
gem_stack: List[Card]
players: List[Player]
_players: List[Player]
started: bool
@@ -26,7 +26,13 @@ class Game:
def start_game(self):
pass
def create_player(self, username: str, team=Team()) -> Player:
def create_player(self, username: str, team: Team) -> Player:
player = Player(username, team)
self.players.append(player)
return player
def create_team(self) -> Team:
return Team()
def serialize():
return super().serialize()
+12 -2
View File
@@ -1,8 +1,8 @@
from typing import List
from game import Card, Team
from game import Card, Team, Serializable
class Player:
class Player(Serializable):
"""Game player, controller by a Client"""
username: str
@@ -21,3 +21,13 @@ class Player:
self.board = []
self.team = team
self.username = username
def serialize_limited(self) -> dict:
return {
"username": self.username,
"stack_pile_amount": len(self.stack_pile),
"discard_pile": [card.serialize() for card in self.discard_pile],
"team": self.team.id,
"hand_amount": len(self.hand),
"board": [card.serialize() for card in self.board],
}
+3
View File
@@ -0,0 +1,3 @@
class Serializable:
def serialize(self):
return self.__dict__
+10 -5
View File
@@ -1,15 +1,20 @@
class Team:
from game import Serializable
class Team(Serializable):
"""Shared object for health storage"""
_team_id = 1
id = 1
health: int
color: str
name: str
def __init__(self, health=80, color="red", name="Team " + str(_team_id)):
self._team_id = Team._team_id
Team._team_id += 1
def __init__(self, health=80, color="red", name="Team " + str(id)):
self.id = Team.id
print(self.id, Team.id)
Team.id += 1
print(self.id, Team.id)
self.health = health
self.color = color
self.name = name
+4 -11
View File
@@ -1,19 +1,12 @@
from typing import Optional, Any
from typing import Any
from pydantic import BaseModel
class MessageData(BaseModel):
message: Optional[Any] = None
class Message(BaseModel):
type: str
data: MessageData
class LoginData(MessageData):
username: str
data: Any | str | int | None = None
data_type: str
class LoginMessage(Message):
data: LoginData
data: str
+6 -1
View File
@@ -2,6 +2,7 @@ import asyncio
from typing import Set, Callable, Any, List
from websockets.server import serve, WebSocketServerProtocol
from websockets import broadcast
import time
class WSServer:
@@ -11,6 +12,8 @@ class WSServer:
message_callbacks: List[Callable[[WebSocketServerProtocol], Any]]
port: 0
def __init__(self):
self.connections = set()
self.message_callbacks = []
@@ -27,7 +30,7 @@ class WSServer:
async def track_connection(self, websocket: WebSocketServerProtocol):
"""Keeps track of connected clients in the connections property"""
self.connections.add(websocket)
try:
await websocket.wait_closed()
finally:
@@ -36,6 +39,8 @@ class WSServer:
async def serve(self, address="0.0.0.0", port=8765):
"""Call to start the websocket"""
self.port = port
async with serve(self.handler, address, port):
print("Started server on ws://" + address + ":" + str(port))
await asyncio.Future() # run forever