From 181686189c208d324c0fd5d5cb58f8ce69b65629 Mon Sep 17 00:00:00 2001 From: Jonas Weinz Date: Thu, 21 Mar 2019 17:02:17 +0100 Subject: [PATCH] better matchmaking --- connection_handler.py | 48 ++++++++++- game_manager.py | 185 ------------------------------------------ main.py | 67 +-------------- settings.py | 10 ++- 4 files changed, 55 insertions(+), 255 deletions(-) delete mode 100644 game_manager.py diff --git a/connection_handler.py b/connection_handler.py index e98851c..9af7468 100644 --- a/connection_handler.py +++ b/connection_handler.py @@ -110,7 +110,6 @@ class ConnectionHandler(object): del(self.open_connections_by_id[conn.id]) del(self.open_connections_by_user[conn.user_name]) - async def new_connection(self, socket: websockets.WebSocketServerProtocol, login_msg: str): @@ -167,8 +166,6 @@ class ConnectionHandler(object): } })) - - return conn await socket.send(json.dumps({ @@ -269,7 +266,38 @@ class ConnectionHandler(object): ) async def _on_match_req(self, conn, data): + n_open_matches = len( + self.match_manager.get_matches_for_user(conn.user_name)) + + if n_open_matches >= 5: + await conn.websocket.send( + json.dumps( + { + "type": "match_request_response", + "data": { + "success": False, + "msg": "you have too many active matches to search for a new one" + } + } + ) + ) + return + if data['player'] is None: + if conn.user_name in self.match_queue: + await conn.websocket.send( + json.dumps( + { + "type": "match_request_response", + "data": { + "success": False, + "msg": "you are already searching for a random match" + } + } + ) + ) + return + if len(self.match_queue) > 0: # it's a match! user_a = self.match_queue.pop() @@ -293,6 +321,19 @@ class ConnectionHandler(object): else: opponent = data['player'] + if opponent == conn.user_name: + await conn.websocket.send( + json.dumps( + { + "type": "match_request_response", + "data": { + "success": False, + "msg": "you cannot play against yourself" + } + } + ) + ) + return try: if len(opponent) <= 16 and '\'' not in opponent and '"' not in opponent: if len(self.user_manager.get_user(opponent)) > 0: @@ -322,7 +363,6 @@ class ConnectionHandler(object): ) ) - except Exception as e: print("error processing match request: " + str(data) + str(e)) diff --git a/game_manager.py b/game_manager.py deleted file mode 100644 index c89221b..0000000 --- a/game_manager.py +++ /dev/null @@ -1,185 +0,0 @@ -#!/usr/bin/env python3 - -import asyncio -import websockets -import json - -player_id_queue = set() -sockets = {} - -player_games = {} - - -async def register_user(id, socket): - - if id in player_id_queue or id in player_games: - return False - - player_id_queue.add(id) - sockets[id] = socket - - await matchmaking() - - return True - - -async def unregister_user(id): - if id in player_id_queue: - player_id_queue.remove(id) - del(sockets[id]) - - elif id in player_games: - # we have an active game and have to end it - await player_games[id]._on_end_game(id) - del(player_games[id]) - - -async def process_message(id, json): - if id in player_games: - await player_games[id].processPlayerMessage(id, json) - - -async def create_new_match(): - p_a = player_id_queue.pop() - p_b = player_id_queue.pop() - - s_a = sockets[p_a] - s_b = sockets[p_b] - - del(sockets[p_a]) - del(sockets[p_b]) - - new_game = GameManager(p_a, p_b, p_a, s_a, s_b) - - player_games[p_a] = new_game - player_games[p_b] = new_game - - await new_game.startMatch() - - -async def matchmaking(): - if len(player_id_queue) < 2: - # we need at least 2 users for that - return - - else: - asyncio.ensure_future(create_new_match()) - - -class GameManager(object): - def __init__(self, player_a_id, player_b_id, start_player, socket_a, socket_b): - self.player_a_id = player_a_id - self.player_b_id = player_b_id - - self.socket_a = socket_a - self.socket_b = socket_b - - self.current_player = start_player - - self.game_finished = False - - async def startMatch(self): - - print("match starts") - - start_msg_a = { - 'type': 'game_starts', - 'data': { - 'msg': '...', - 'opponent_name': self.player_b_id, - 'is_first_move': True - } - } - - start_msg_b = { - 'type': 'game_starts', - 'data': { - 'msg': '...', - 'opponent_name': self.player_a_id, - 'is_first_move': False - } - } - - await self.socket_a.send(json.dumps(start_msg_a)) - await self.socket_b.send(json.dumps(start_msg_b)) - - print("start message send to all players") - - async def processPlayerMessage(self, player_id, json_str): - if len(json_str) > 4096: - # something is fishy here - print("received strange message from client") - - print("received message: " + json_str) - - try: - json_dict = json.loads(json_str) - type = json_dict['type'] - data = json_dict['data'] - - if type == "move": - await self._on_move(player_id, data) - - elif type == "end_game": - await self._on_end_game(player_id) - - except Exception as e: - print("" + str(e) + ": received wrong formated message") - - async def _on_move(self, player_id, move_data): - response = {'type': 'move_response'} - response_data = {} - - opponent_response = {'type': 'move'} - opponent_response_data = {} - - opponent_response_data['sub_x'] = move_data['sub_x'] - opponent_response_data['sub_y'] = move_data['sub_y'] - opponent_response_data['x'] = move_data['x'] - opponent_response_data['y'] = move_data['y'] - opponent_response['data'] = opponent_response_data - - if player_id == self.current_player: - - is_a = (self.player_a_id == player_id) - current_socket = self.socket_a if is_a else self.socket_b - opponent_socket = self.socket_b if is_a else self.socket_a - - response_data['success'] = True - response_data['msg'] = "move successful" - - response['data'] = response_data - - await opponent_socket.send(json.dumps(opponent_response)) - await current_socket.send(json.dumps(response)) - - # switch player - self.current_player = self.player_b_id if is_a else self.player_a_id - - else: - print("received move from wrong player") - - is_a = (self.player_a_id == player_id) - current_socket = self.socket_a if is_a else self.socket_b - - response_data["success"] = False - response_data["msg"] = "not your turn!" - - response['data'] = response_data - - await current_socket.send(json.dumps(response)) - - async def _on_end_game(self, player_id): - - if self.game_finished: - return - - is_a = (self.player_a_id == player_id) - opponent_socket = self.socket_b if is_a else self.socket_a - - opponent_response = {'type': 'end_game'} - opponent_response['data'] = {'msg': 'game closed by opponent'} - - await opponent_socket.send(json.dumps(opponent_response)) - - self.game_finished = True diff --git a/main.py b/main.py index edb9f53..e5d4531 100644 --- a/main.py +++ b/main.py @@ -5,7 +5,6 @@ import ssl import traceback -from game_manager import * from session_manager import SessionManager from connection_handler import Connection, ConnectionHandler from match_manager import MatchManager @@ -27,7 +26,7 @@ DatabaseConnection(db_host, db_charset) -async def new_socket_worker(websocket, path): +async def socket_worker(websocket, path): connection = None print("new incomin connection") @@ -68,69 +67,11 @@ async def new_socket_worker(websocket, path): id = "unknown_user" print("close connection to user: " + id) - -async def socket_worker(websocket, path): - - registered = False - id = None - - print("new connection") - - try: - # get first message as register message - raw_msg = await websocket.recv() - - msg = json.loads(raw_msg) - - if msg['type'] != 'register': - print("got wrong registration") - websocket.close() - return - - id = msg['data']['id'] - - registered = await register_user(id, websocket) - - register_response = { - 'type': 'register_response', 'data': { - 'success': True, 'msg': '...'}} - - if not registered: - register_response['data']['success'] = False - - await websocket.send(json.dumps(register_response)) - websocket.close() - return - - await websocket.send(json.dumps(register_response)) - - print("successful redisterd user " + id) - - async for m in websocket: - await process_message(id, m) - - except Exception as e: - # TODO: each disconnect is an exception so far - if id is not None: - print("catched exception in worker for user: " + id + ": " + str(e)) - else: - print("catched exception in worker for unknown user") - - - finally: - if registered: - await unregister_user(id) - - if id is None: - id = "unknown_user" - print("close connection to user: " + id) - - -#ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) -#ssl_context.load_cert_chain(cert_file, keyfile=key_file) +ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) +ssl_context.load_cert_chain(cert_file, keyfile=key_file) start_server = websockets.serve( - new_socket_worker, host='', port=server_port) # , ssl=ssl_context) + socket_worker, host='', port=server_port, ssl=ssl_context) asyncio.get_event_loop().run_until_complete(start_server) asyncio.get_event_loop().run_forever() diff --git a/settings.py b/settings.py index 28f82d5..971723c 100644 --- a/settings.py +++ b/settings.py @@ -6,7 +6,11 @@ server_port = 5556 db_host = "127.0.0.1" db_port = 3306 -db_user = "tictactoe" -dp_pw = "" +db_user = None +db_pw = None +db_db = None -charset = 'utf8mb4' +db_charset = 'utf8mb4' + +# field dimension +n = 3