All checks were successful
continuous-integration/drone/push Build is passing
122 lines
3.7 KiB
Python
122 lines
3.7 KiB
Python
import json
|
|
|
|
from collections import OrderedDict
|
|
from typing import Any, Iterator, Optional
|
|
|
|
from glebby.board import BoardGenerator
|
|
from glebby.connection_manager import ConnectionManager
|
|
|
|
class Client:
|
|
id: int
|
|
name: str
|
|
|
|
def __init__(self, client_id: int):
|
|
self.id = client_id
|
|
self.name = ''
|
|
|
|
def get_dto(self) -> dict[str, Any]:
|
|
return { 'id': self.id, 'name': self.name }
|
|
|
|
class Model:
|
|
connection_manager: ConnectionManager
|
|
clients: OrderedDict[int, Client]
|
|
board_generator: BoardGenerator
|
|
board: Optional[list[list[str]]]
|
|
|
|
def __init__(self, connection_manager: ConnectionManager):
|
|
self.connection_manager = connection_manager
|
|
self.clients = OrderedDict()
|
|
self.board_generator = BoardGenerator(None)
|
|
self.board = None
|
|
|
|
self.connection_manager.on_open = self.add_client
|
|
self.connection_manager.on_message = self.handle_incoming
|
|
self.connection_manager.on_close = self.remove_client
|
|
|
|
# Event handlers
|
|
|
|
async def add_client(self, client_id: int) -> None:
|
|
print(f'<{client_id}|OPEN>')
|
|
|
|
await self.broadcast(client_id, {
|
|
'type': 'join'
|
|
})
|
|
self.clients[client_id] = Client(client_id)
|
|
await self.send_to(None, client_id, {
|
|
'type': 'init',
|
|
'state': self.get_state_dto(client_id)
|
|
})
|
|
|
|
async def remove_client(self, client_id: int) -> None:
|
|
print(f'<{client_id}|CLOS>')
|
|
|
|
del self.clients[client_id]
|
|
await self.broadcast(client_id, {
|
|
'type': 'leave'
|
|
})
|
|
|
|
async def handle_incoming(self, client_id: int, data: str) -> None:
|
|
print(f'<{client_id}|DATA> {data}')
|
|
|
|
try:
|
|
payload = json.loads(data)
|
|
except:
|
|
await self.send_to(None, client_id, {
|
|
'type': 'error',
|
|
'errorMessage': 'you sent invalid JSON!'
|
|
})
|
|
return
|
|
|
|
if 'type' not in payload:
|
|
await self.send_to(None, client_id, {
|
|
'type': 'error',
|
|
'errorMessage': 'missing message type!'
|
|
})
|
|
return
|
|
|
|
match payload:
|
|
case {'type': 'set-name', 'name': name}:
|
|
self.clients[client_id].name = name
|
|
await self.broadcast(client_id, {
|
|
'type': 'set-name',
|
|
'name': name
|
|
})
|
|
|
|
case {'type': 'chat', 'message': message}:
|
|
await self.broadcast(client_id, {
|
|
'type': 'chat',
|
|
'message': message
|
|
})
|
|
|
|
case {'type': 'roll'}:
|
|
self.board = self.board_generator.generate_board()
|
|
await self.broadcast(client_id, {
|
|
'type': 'roll',
|
|
'board': self.board
|
|
})
|
|
|
|
case _:
|
|
print(' Unhandled!')
|
|
|
|
def get_state_dto(self, client_id: int) -> Any:
|
|
return {
|
|
'yourId': client_id,
|
|
'players': [
|
|
client.get_dto()
|
|
for client in self.clients.values()
|
|
],
|
|
'board': self.board
|
|
}
|
|
|
|
# Message sending
|
|
|
|
async def send_to(self, client_id_from: Optional[int], client_id_to: int, payload: Any) -> None:
|
|
await self.connection_manager.send_to(client_id_to, json.dumps({
|
|
'from': client_id_from,
|
|
'payload': payload
|
|
}))
|
|
|
|
async def broadcast(self, client_id_from: Optional[int], payload: Any) -> None:
|
|
for client_id_to in self.clients:
|
|
await self.send_to(client_id_from, client_id_to, payload)
|