diff --git a/requirements.txt b/requirements.txt index 0768f44..eefc955 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,8 @@ gevent==24.2.1 greenlet==3.0.3 +mypy==1.9.0 +mypy-extensions==1.0.0 +typing_extensions==4.10.0 websockets==12.0 zope.event==5.0 zope.interface==6.2 diff --git a/src/game/__init__.py b/src/game/__init__.py index e040e07..777a568 100644 --- a/src/game/__init__.py +++ b/src/game/__init__.py @@ -1,4 +1,4 @@ from game.card import Card -from game.game import Game -from game.player import Player from game.team import Team +from game.player import Player +from game.game import Game diff --git a/src/game/game.py b/src/game/game.py index 4c4921a..a1d3fac 100644 --- a/src/game/game.py +++ b/src/game/game.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -from typing import List +from typing import List, Callable, Coroutine, Any from game import Card, Team @@ -16,6 +16,8 @@ class Game: default_health = 80 + broadcast: Callable[[str], Coroutine[Any, Any, Any]] + def __init__(self): self.market_stack = [] self.market = [] @@ -26,5 +28,5 @@ class Game: def create_team(self): if self.started: return False - team = Team(self, health=self.default_health) + team = Team(health=self.default_health) self.teams.append(team) diff --git a/src/game/team.py b/src/game/team.py index 1e465ac..ddccd9b 100644 --- a/src/game/team.py +++ b/src/game/team.py @@ -1,34 +1,15 @@ -from typing import List -from game import Game, Player - - class Team: - """Handles health and hand visibility for players""" + """Shared object for health storage""" _team_id = 1 - game: Game - players: List[Player] - health: int color: str name: str - def __init__(self, game, health=80, color="red", name="Team " + _team_id): + def __init__(self, health=80, color="red", name="Team " + str(_team_id)): + self._team_id = Team._team_id Team._team_id += 1 - self.game = game - self.players = [] - self.health = health self.color = color self.name = name - - def delete(self): - """Get garbage collected you idiot""" - if len(self.players) == 0: - self.game.teams.remove(self) - else: - raise Warning("Tried to delete an empty team!") - - def removePlayer(self): - pass diff --git a/src/main.py b/src/main.py index bbb00ae..821e04c 100644 --- a/src/main.py +++ b/src/main.py @@ -1,3 +1,12 @@ #!/usr/bin/env python +import asyncio +from game import Game -from game.Game import Game +from netcode import WSServer + +gameServer = WSServer() +hero_game = Game() +hero_game.broadcast = gameServer.broadcast + + +asyncio.run(gameServer.serve()) diff --git a/src/netcode/__init__.py b/src/netcode/__init__.py new file mode 100644 index 0000000..cc1b466 --- /dev/null +++ b/src/netcode/__init__.py @@ -0,0 +1 @@ +from netcode.ws_server import WSServer diff --git a/src/netcode/ws_server.py b/src/netcode/ws_server.py new file mode 100644 index 0000000..cdb5053 --- /dev/null +++ b/src/netcode/ws_server.py @@ -0,0 +1,45 @@ +import asyncio +from typing import Set +from websockets.server import serve, WebSocketServerProtocol +from websockets import broadcast + + +class WSServer: + """Handles Client-Server communication""" + + connections: Set[WebSocketServerProtocol] + + def __init__(self): + self.connections = set() + + async def _handler(self, websocket: WebSocketServerProtocol): + """Is called everytime a client connects to the websocket""" + + await asyncio.wait( + [self._track_connection(websocket), self._message_handler(websocket)] + ) + + async def _message_handler(self, websocket: WebSocketServerProtocol): + """Handles recieving messages from the client""" + + async for message in websocket: + await websocket.send(message) + + async def _track_connection(self, websocket: WebSocketServerProtocol): + """Keeps track of connected clients in the connections property""" + + try: + await websocket.wait_closed() + finally: + self.connections.remove(websocket) + + async def serve(self, address="0.0.0.0", port=8765): + """Call to start the websocket""" + + async with serve(self._handler, address, port): + print("Started server on ws://" + address + ":" + str(port)) + await asyncio.Future() # run forever + + async def broadcast(self, message: str): + """Broadcast a message to all connected clients""" + broadcast(self.connections, message)