def __init__(self): self.log = Log(self.__class__) self.db_port = 3306 # Getting computer WAN address self.computerAddress = self.get_ip_address() self.config = self.get_config() if ("armv7" in platform()) and ("178.132." not in self.computerAddress): self.raspberry = True self.ssh_connection = None else: self.raspberry = False self.ssh_host = self.config['Connection']['SSH']['host'] self.ssh_port = self.config['Connection']['SSH']['port'] self.ssh_username = self.config['Connection']['SSH']['username'] self.ssh_password = self.config['Connection']['SSH']['password'] self.ssh_connection = self.ssh_connect() if self.ssh_connection is not None: self.db_port = self.ssh_connection.local_bind_port self.log.log_all( 3, "Local bind port: " + str(self.ssh_connection.local_bind_port)) self.db_host = self.config['Connection']['DataBase']['host'] self.db_username = self.config['Connection']['DataBase']['username'] self.db_password = self.config['Connection']['DataBase']['password'] self.db_name = self.config['Connection']['DataBase']['database_name'] self.database_connection = self.database_connect() self.cursor = (self.database_connection.cursor(dictionary=True) if self.database_connection.is_connected() else None)
def __init__(self, cursor: DBCore, users: dict, addr): self.cursor = cursor self.dungeon_generator = DungeonSkeleton(cursor=self.cursor) self.connected_users = users self.addr = addr self.user_key = f"{self.addr.host}:{self.addr.port}" self.player = UserModule self.log_file = Log(class_name=self.__class__) self.actions = { "default": UtilityModule.generate_response, "playerRegistration": self.player_registration, "playerAuthorization": self.player_authorization, "getDungeonSkeleton": self.get_dungeon_skeleton, "startBattle": self.start_battle, "getLoot": self.generate_loot, "sendChatMessage": self.send_chat_message, "sendPrivateMessage": self.send_private_message }
def __init__(self, cursor: DBCore): self.log_file = Log(class_name=self.__class__) self.cursor = cursor self.all_mobs = self._generate_mobs()
class DungeonSkeleton: """ Module which generates random dungeon skeleton with mobs for player """ def __init__(self, cursor: DBCore): self.log_file = Log(class_name=self.__class__) self.cursor = cursor self.all_mobs = self._generate_mobs() def final_dungeon_skeleton(self, player_data: UserModule) -> dict: """ Create final dungeon structure for a player from: 1 -> dungeon structure 2 -> available mobs which are little modified by adding level :return: Dictionary representing final dungeon structure for player """ graph_structure = self._generate_graph_structure() for room in graph_structure['rooms']: graph_structure['mobs'][room] = {} for mob_uid in range(0, random.choice([1, 2, 3])): mob = copy.deepcopy(self.all_mobs[random.choice( range(1, len(self.all_mobs.keys())))]) mob['mob_level'] = 1 if player_data.level - 2 < 1 else random.choice( range(player_data.level - 2, player_data.level)) mob['stats']['hits'] = mob['stats'][ 'hits'] if player_data.level - 2 < 1 else mob['stats'][ 'hits'] * 2.5 graph_structure['mobs'][room][mob_uid] = mob self.log_file.log_all(priority=3, string=f"Dungeon skeleton filled with mobs") return graph_structure def _generate_graph_structure(self) -> dict: """ Generate random graph structure with given number of nodes and % of routes :return: Dictionary representing graph structure """ nodes_counter = random.choice(range(5, 10)) percent_of_routes = 0.4 graph = erdos_renyi_graph(nodes_counter, percent_of_routes) edges = [] for edge in graph.edges: edges.append(list(edge)) self.log_file.log_all(priority=3, string=f"Dungeon skeleton generated") return {"rooms": list(graph.nodes), "routes": edges, "mobs": {}} def _generate_mobs(self) -> dict: """ Generate mobs from available mobs in the DataBase :return: Dictionary of all available mobs """ available_mobs = self.cursor.get_dungeon_mobs() all_vulnerabilities = self.cursor.get_mobs_vulnerabilities() all_attacks = self.cursor.get_mobs_attacks() all_stats = self.cursor.get_mobs_stats() generated_mobs = {} for mob in available_mobs: mob_id = mob[list(mob)[0]] mob_attacks = self._mob_data_parser(mob_id, all_attacks) mob_vulnerabilities = self._mob_data_parser( mob_id, all_vulnerabilities) mob_stats = self._mob_data_parser(mob_id, all_stats, stats_flag=True) generated_mobs[mob['enemy_id']] = { "name": mob['name'], "desc": mob['description'], "attacks": mob_attacks, "stats": mob_stats, "vulnerabilities": mob_vulnerabilities, "inventory": {} } self.log_file.log_all(priority=3, string=f"Mobs Generated") return generated_mobs @staticmethod def _mob_data_parser(mob_id: int, data: dict, stats_flag=False) -> dict: """ Parsing data about mobs :param mob_id: Id of the mob :param data: Data to parse :param stats_flag: Flag used to determine if stats dict is being parse :return: """ end_data = {} for item in data: enemy_id = item[list(item)[0]] stats_id = item[list(item)[1]] temp = item.copy() del temp[list(temp)[0]] if not stats_flag: del temp[list(temp)[0]] if mob_id == enemy_id: if not stats_flag: end_data[stats_id] = temp else: end_data = temp return end_data
""" server.py: Script that starts DND server """ __author__ = "Runtov Constantin, Mandrila Daniel" __copyright__ = "Copyright 2020, The Earth" __credits__ = ["Runtov Constantin", "Mandrila Daniel"] __license__ = "USM" __version__ = "0.2" __maintainer__ = "Gheorghe Latul" __email__ = "*****@*****.**" __status__ = "Developing" from twisted.internet import reactor from src.Server import ServerFactory from src.Logging.Logger import Log if __name__ == '__main__': log_file = Log( class_name=__name__ ) reactor.listenTCP(1309, ServerFactory()) try: log_file.log_all(3, "Started") reactor.run() except KeyboardInterrupt as e: reactor.close() log_file.log_all(3, "Stopped")
class MySQLModule: """ Class which describes behaviour of connection to the DataBase """ def __init__(self): self.log = Log(self.__class__) self.db_port = 3306 # Getting computer WAN address self.computerAddress = self.get_ip_address() self.config = self.get_config() if ("armv7" in platform()) and ("178.132." not in self.computerAddress): self.raspberry = True self.ssh_connection = None else: self.raspberry = False self.ssh_host = self.config['Connection']['SSH']['host'] self.ssh_port = self.config['Connection']['SSH']['port'] self.ssh_username = self.config['Connection']['SSH']['username'] self.ssh_password = self.config['Connection']['SSH']['password'] self.ssh_connection = self.ssh_connect() if self.ssh_connection is not None: self.db_port = self.ssh_connection.local_bind_port self.log.log_all( 3, "Local bind port: " + str(self.ssh_connection.local_bind_port)) self.db_host = self.config['Connection']['DataBase']['host'] self.db_username = self.config['Connection']['DataBase']['username'] self.db_password = self.config['Connection']['DataBase']['password'] self.db_name = self.config['Connection']['DataBase']['database_name'] self.database_connection = self.database_connect() self.cursor = (self.database_connection.cursor(dictionary=True) if self.database_connection.is_connected() else None) @staticmethod def get_ip_address() -> str: """ Method to get ip address of the device on which script is being start :return: """ from requests import get return get('https://api.ipify.org').text def get_config(self) -> dict: """ Method which gets config file based on ip address of the device :return: """ try: with open( "{}/{}.json".format( os.path.abspath('src/Config'), ("home_connection_config" if "178.132." in self.computerAddress else "config")), "r") as file: config = json.load(file) return config except IOError as io_error: self.log.log_all(1, str(io_error)) # print(io_error) def database_connect(self) -> maria_db.connect: """ Method to connect to the DataBase :return: database connection object """ try: self.database_connection = maria_db.connect( host=self.db_host, database=self.db_name, user=self.db_username, password=self.db_password, port=self.db_port) self.log.log_all(3, "DataBase connection made") return self.database_connection except maria_db.Error as e: self.log.log_all(1, f"Connection error: {str(e)}") self.disconnect() return None def check_database_connection(self): """ Method to check database connection :return: """ if not self.database_connection.is_connected(): self.database_connection.reconnect(10, 1) def ssh_connect(self): """ Method by which SSH tunnel is create :return: SSHTunnelForwarder if connection created or None """ try: from sshtunnel import SSHTunnelForwarder, BaseSSHTunnelForwarderError try: ssh_connection = SSHTunnelForwarder( (self.ssh_host, self.ssh_port), ssh_username=self.ssh_username, ssh_password=self.ssh_password, remote_bind_address=(self.config['Connection']['SSH'] ['remote_bind_address']['host'], self.config['Connection']['SSH'] ['remote_bind_address']['port'])) ssh_connection.start() self.log.log_all(3, "SSH Tunnel made") return ssh_connection except BaseSSHTunnelForwarderError as ssh_error: self.log.log_all(2, str(ssh_error)) return None except ImportError as import_error: self.log.log_all(1, str(import_error)) def disconnect(self): """ Module which closes connection to the DataBase :return: """ if self.database_connection.is_connected(): self.cursor.close() self.database_connection.close() self.log.log_all(3, "Database Connection closed") try: if (not self.raspberry) or self.ssh_connection: if self.ssh_connection.is_active: self.ssh_connection.close() self.log.log_all(3, "SSH tunnel closed") except AttributeError as e: self.log.log_all(1, str(e)) def select_query(self, query): """ Module which executes SELECT query on the DataBase :param query: query to execute :return: """ try: self.check_database_connection() self.cursor.execute(query) return self.cursor.fetchall() except maria_db.Error as error: self.log.log_all(1, str(error)) # raise custom_error_exception("Error to execute query", error) raise DBExceptions.QueryExecuteError("Error to execute query:", error) def insert_query(self, query) -> int: """ Module which executes INSERT query on the DataBase :param query: query to execute :return: """ try: self.check_database_connection() self.cursor.execute(query) self.database_connection.commit() return 1 except maria_db.Error as error: self.log.log_all(1, str(error)) # raise custom_error_exception("Error to execute query", error) raise DBExceptions.QueryExecuteError("Error to execute query:", error)
def __init__(self): super(DBCore, self).__init__() self.log = Log(self.__class__)
class DBCore(MySQLModule): """ Class which contains methods to get useful data from DataBase """ def __init__(self): super(DBCore, self).__init__() self.log = Log(self.__class__) def database_info(self): """ Get information about DataBase version,Name and log this to file :return: """ self.log.log_all( 3, "Connected to MariaDB version: " + self.database_connection.get_server_info()) self.log.log_all(3, "Connected to Database: " + self.db_name) def get_animals(self): """ Getting animals from DataBase :return: """ animals = self.select_query(""" SELECT name, price, speed, capacity FROM Animals; """) return animals def get_weapons(self): """ Getting weapons from DataBase :return: """ weapons = self.select_query(""" SELECT * FROM Weapons """) return weapons def get_classes(self): """ Getting classes from DataBase :return: """ classes = self.select_query(""" SELECT class_name FROM Classes; """) return classes def get_races(self): """ Getting races from DataBase :return: """ races = self.select_query(""" SELECT name FROM Races; """) return races def get_food(self): """ Getting available food from DataBase :return: """ food = self.select_query(""" SELECT * FROM Food; """) return food def get_armor(self): """ Getting available armor from DataBase :return: """ armor = self.select_query(""" SELECT * FROM Armor """) return armor def check_player(self, name, password) -> int: """ Checking player for existing in DataBase :param name: Player name :param password: Player password :return: """ exists = self.select_query(f""" SELECT EXISTS( SELECT player_name from Players WHERE player_name = '{name}' AND player_password = '******' ) AS `exists`; """) return exists[0]['exists'] def check_player_name(self, name) -> int: """ Checking player name for existing in DataBase :param name: Player name :return: """ exists = self.select_query(f""" SELECT EXISTS( SELECT player_name from Players WHERE player_name = '{name}' ) AS `exists`; """) return exists[0]['exists'] def add_player(self, name, password, class_id, race_id): """ Adding player to the DataBase :param name: Player name :param password: Player password :param class_id: Player class id :param race_id: Player race id :return: """ return self.insert_query(f""" INSERT INTO Players (player_name, player_password, lvl, experience, class_id, race_id) VALUES('{name}', '{password}', 1, 0, {class_id}, {race_id}) """) def get_player_main_data(self, name): """ Getting main data about a player from DataBase :param name: Player Name :return: """ return self.select_query(f"""SELECT `p`.`player_id`, `p`.`player_name`, `p`.`lvl`, `p`.`experience`, `p`.`class_id`, `c`.`class_name`, `p`.`race_id`, `r`.`name` AS `race`, `s`.* FROM Players AS p LEFT JOIN Races AS r ON r.race_id = p.race_id LEFT JOIN Classes AS c ON c.class_id = p.class_id LEFT JOIN Stats AS s ON s.hero_id = p.player_id WHERE player_name = '{name}' """) def get_player_food(self, player_id): """ Getting players food from DataBase :param player_id: Player id :return: """ return self.select_query(f""" SELECT `fe`.`food_id`, `f`.`name` AS `food_name`, `f`.`price` AS `food_price` FROM `Food_Equipment` AS `fe` INNER JOIN `Food` AS `f` ON `f`.`food_id` = `fe`.`food_id` WHERE `fe`.`equipment_id` = '{player_id}' """) def get_player_armor(self, player_id): """ Getting players armor from DataBase :param player_id: Player id :return: """ return self.select_query(f""" SELECT `ae`.`armor_id`, `a`.`name` AS `armor_name`, `a`.`armor_weight`, `a`.`armor_price` FROM `Armor_Equipment` AS `ae` INNER JOIN `Armor` AS `a` ON `a`.`armor_id` = `ae`.`armor_id` WHERE `ae`.`equipment_id` = '{player_id}' """) def get_player_weapons(self, player_id): """ Getting players weapons from DataBase :param player_id: Player id :return: """ return self.select_query(f""" SELECT `we`.`weapons_id`, `w`.`name` AS `weapon_name`, `w`.`price` AS `weapon_price`, `w`.`damage_min`, `w`.`damage_max`, `w`.`weight` AS `weapon_weight` FROM `Weapon_Equipment` AS `we` INNER JOIN `Weapons` AS `w` ON `w`.weapons_id = `we`.`weapons_id` WHERE `we`.`equipment_id` = '{player_id}' """) def get_player_animals(self, player_id): """ Getting players animals from DataBase :param player_id: Player id :return: """ return self.select_query(f""" SELECT `ae`.`animal_id`, `a`.`name` AS `animal_name`, `a`.`price` AS `animal_price`, `a`.`speed` AS `animal_speed`, `a`.`capacity` AS `animal_capacity` FROM `Animals_Equipment` AS `ae` INNER JOIN `Animals` AS `a` ON `a`.`animal_id` = `ae`.`animal_id` WHERE `ae`.`equipment_id` = '{player_id}' """) def get_player_attacks(self, class_id, lvl): """ Getting players attacks from DataBase :param class_id: Players class id :param lvl: lvl :return: """ return self.select_query(f""" SELECT `ca`.`attack_id`, `a`.`name` AS `attack_name`, `a`.`lvl`, `a`.`type_attack`, `a`.`count_of_random`, `a`.`cooldown`, `a`.`random_diapason`, `a`.`effect` FROM `Classes_Attacks` AS `ca` INNER JOIN `Attacks` AS `a` ON `ca`.`attack_id` = `a`.`attack_id` WHERE `ca`.`class_id` = '{class_id}' AND `a`.`lvl` <= '{lvl}' """) def get_player_vulnerabilities(self, player_id): """ Getting players vulnerabilities from DataBase :param player_id: Player id :return: """ return self.select_query(f""" SELECT `pv`.`vulnerability_id`, `v`.`vulnerability_name`, `v`.`vulnerability_description` FROM `Players_Vulnerabilities` AS `pv` INNER JOIN `Vulnerabilities` AS `v` ON `v`.`vulnerability_id` = `pv`.`vulnerability_id` WHERE `pv`.`player_id` = '{player_id}' """) def get_player(self, player_name): """ Getting player info from DataBase :param player_name: Player name :return: """ main_data = self.get_player_main_data(player_name) player_id = main_data[0]['player_id'] class_id = main_data[0]['class_id'] lvl = main_data[0]['lvl'] food = self.get_player_food(player_id) armor = self.get_player_armor(player_id) weapons = self.get_player_weapons(player_id) animals = self.get_player_animals(player_id) vulnerabilities = self.get_player_vulnerabilities(player_id) attacks = self.get_player_attacks(class_id, lvl) return { 'main': main_data, 'food': food, 'armor': armor, 'weapons': weapons, 'animals': animals, 'vulnerabilities': vulnerabilities, 'attacks': attacks } def get_dungeon_mobs(self): """ Getting available mobs from DataBase :return: """ return self.select_query(f""" SELECT * FROM `Enemies` """) def get_mobs_attacks(self): """ Getting available mob attacks from DataBase :return: """ return self.select_query(f""" SELECT ea.enemy_id, `a`.* FROM Enemies_Attacks AS ea INNER JOIN Attacks AS a ON a.attack_id = ea.attack_id """) def get_mobs_vulnerabilities(self): """ Getting available mob vulnerabilities from DataBase :return: """ return self.select_query(f""" SELECT ev.enemy_id, v.* FROM Enemies_Vulnerabilities AS ev INNER JOIN Vulnerabilities AS v ON v.vulnerability_id = ev.vulnerability_id """) def get_mobs_stats(self): """ Getting available mob stats :return: """ return self.select_query(f""" SELECT s.* FROM `Enemies` AS `e` INNER JOIN Enemy_Stats AS s ON e.enemy_id = s.hero_id """) def get_loot(self): return { "weapons": self.get_weapons(), "armor": self.get_armor(), "food": self.get_food() }
def __init__(self): self.log_file = Log(self.__class__) self.six_side = 6 self.eight_side = 8 self.twelve_side = 12 self.twenty_side = 20
class UserHandler(LineReceiver, ABC): """ Heart of the server """ def __init__(self, cursor: DBCore, users: dict, addr): self.cursor = cursor self.dungeon_generator = DungeonSkeleton(cursor=self.cursor) self.connected_users = users self.addr = addr self.user_key = f"{self.addr.host}:{self.addr.port}" self.player = UserModule self.log_file = Log(class_name=self.__class__) self.actions = { "default": UtilityModule.generate_response, "playerRegistration": self.player_registration, "playerAuthorization": self.player_authorization, "getDungeonSkeleton": self.get_dungeon_skeleton, "startBattle": self.start_battle, "getLoot": self.generate_loot, "sendChatMessage": self.send_chat_message, "sendPrivateMessage": self.send_private_message } def log_to_debug(self, line: str) -> None: """ Log to the debug file :param line: Line to log """ with open("Logs/debug.log", "a") as f: f.writelines(f"{self.user_key} | {datetime.now()} | {line}\n") @staticmethod def log_account_info(username: str, password: str) -> None: """ Log players Username and Password :param username: Players username :param password: Players password :return: """ with open("Logs/user_registry.log", "a") as file: file.writelines( f"Registered: {datetime.now()} | Username: {username} | Password: {password}\n" ) def connectionMade(self): """ Sending response that connection made and adding to connections list :return: """ self.connected_users[self.user_key] = { "host": self.addr.host, "type": self.addr.type, "authorized": False, "main": { "player_name": None, "base": None, "dungeon": None }, } self.log_to_debug( line=f"{self.addr.host}:{self.addr.port} Connected...") self.log_file.log_all( priority=3, string=f"{self.addr.host}:{self.addr.port} Connected to server") self.send_one(response=UtilityModule.generate_response( action="connectToServer", code=100)) def lineReceived(self, line: bytes): """ Receive line and parse it to json_data. Call method depending on action stored in json_data :param line: :return: """ try: json_data = json.loads(line.decode("utf8")) action = json_data['action'] try: self.log_to_debug(line=f"Received line: {json_data}") if action in self.actions: self.actions.get(action)(action, json_data) else: self.send_one( response=self.actions.get("default")(action, 403)) except Exception as exception: self.log_file.log_all(priority=2, string=str(exception)) self.send_one(response=UtilityModule.generate_response( action=action, code=400)) except json.decoder.JSONDecodeError as json_decode_error: self.log_file.log_all(priority=2, string=str(json_decode_error)) self.send_one(response=UtilityModule.generate_response(action=None, code=401)) def connectionLost(self, reason=twisted_error): """ Deleting connection from connections list if lost :param reason: :return: """ if self.connected_users and self.user_key in self.connected_users: self.log_to_debug( line= f"DELETE CONNECTION WITH < {self.addr.host}:{self.addr.port} >" f" -> Reason: {reason.getErrorMessage()}") del self.connected_users[self.user_key] self.log_file.log_all( priority=3, string=f"Connection lost with {self.addr.host}:{self.addr.port} " f"-> Reason: {reason.getErrorMessage()}") def player_registration(self, action: str, json_data: Any) -> None: """ Registration of specified player :param action: String used to generate response :param json_data: Received data from the client :return: """ try: if self.cursor.check_player_name( name=json_data['data']['player_name']) == 1: self.send_one(response=UtilityModule.generate_response( action=action, code=405)) elif self.cursor.add_player( name=json_data['data']['player_name'], password=UtilityModule.encrypt_password( player_password=json_data['data']['player_password']), class_id=json_data['data']['class_id'], race_id=json_data['data']['race_id']) == 1: self.send_one(response=UtilityModule.generate_response( action=action, code=202)) self.log_account_info( username=json_data['data']['player_name'], password=json_data['data']['player_password']) self.log_file.log_all( priority=3, string= f"Player < {json_data['data']['player_name']} > successfully registered" ) except DBExceptions.QueryExecuteError as query_exec_error: self.send_one(response=UtilityModule.generate_response( action=action, code=400)) self.log_file.log_all(priority=2, string=str(query_exec_error)) def player_authorization(self, action: str, json_data: Any) -> None: """ Authorization of specified player :param action: String used to generate response :param json_data: Received data from the client :return: """ def check_for_user_not_in_system(player_name: str) -> bool: """ Checking if user with given username already logged :param player_name: :return: """ for uid, user in self.connected_users.items(): if user['authorized'] and user['main'][ 'player_name'] == player_name: return False return True try: if self.cursor.check_player_name( name=json_data['data']['player_name']) == 1: if check_for_user_not_in_system(json_data['data']['player_name']) \ or len(self.connected_users) == 1: if self.cursor.check_player( name=json_data['data']['player_name'], password=UtilityModule.encrypt_password( player_password=json_data['data'] ['player_password'])) == 1: self.player = UserModule( player_data=self.cursor.get_player( player_name=json_data['data']['player_name'])) self.connected_users[self.user_key]['main'][ 'player_name'] = self.player.player_name self.connected_users[ self.user_key]['main']['base'] = self self.connected_users[ self.user_key]['authorized'] = True self.send_one(response=UtilityModule.generate_response( action=action, code=203, data=self.player.get_player())) self.log_file.log_all( priority=3, string= f"Player < {json_data['data']['player_name']} > successfully authorized" ) else: self.send_one(response=UtilityModule.generate_response( action=action, code=408)) else: self.send_one(response=UtilityModule.generate_response( action=action, code=409)) else: self.send_one(response=UtilityModule.generate_response( action=action, code=408)) except DBExceptions.QueryExecuteError as query_exec_error: self.send_one(response=UtilityModule.generate_response( action=action, code=400)) self.log_file.log_all(priority=2, string=str(query_exec_error)) def get_dungeon_skeleton(self, action: str, json_data: Any) -> None: """ Generate and send dungeon skeleton for the player :param action: String used to generate response :param json_data: Received data from the client :return: """ try: if self.connected_users[self.user_key].get('authorized'): skeleton = self.dungeon_generator.final_dungeon_skeleton( player_data=self.player) self.connected_users[self.user_key]['main']['dungeon'] = { 'skeleton': skeleton, 'passed': False } self.send_one(response=UtilityModule.generate_response( action=action, code=201, data={"dungeonSkeleton": skeleton})) else: self.send_one(response=UtilityModule.generate_response( action=action, code=406)) except Exception as exception: self.log_file.log_all(priority=2, string=str(exception)) self.send_one(response=UtilityModule.generate_response( action=action, code=400)) def start_battle(self, action: str, json_data: Any) -> None: """ Method for invoking battle between a player and given enemy :param action: String used to generate response :param json_data: Received data from the client :return: """ battle = BattleModule.BattleModule( player=self.player, battle_data=json_data['data']).battle_result() self.send_one(response=UtilityModule.generate_response( action=action, code=205, data=battle)) def generate_loot(self, action: str, json_data: Any) -> None: """ Method to generate loot after passing the dungeon :param action: String used to generate response :param json_data: Received data from the client :return: """ if self.connected_users[self.user_key]['authorized']: if self.connected_users[self.user_key]['main'][ 'dungeon']: # fixme check if dungeon complete available_loot = self.cursor.get_loot() self.connected_users[ self.user_key]['main']['dungeon']['passed'] = True result = LootModule.LootModule(dungeon=self.connected_users[ self.user_key]['main']['dungeon']['skeleton'], player=self.player, loot=available_loot).get_loot() result['level'] = self.player.level_up( received_experience=result['level']) self.send_one(response=UtilityModule.generate_response( action=action, code=204, data=result)) del result del available_loot else: self.send_one(response=UtilityModule.generate_response( action=action, code=410)) else: self.send_one(response=UtilityModule.generate_response( action=action, code=406)) def send_private_message(self, action: str, json_data: Any) -> None: """ Sending message to the another specified user from a specified player :param action: String used to generate response :param json_data: Received data from the client :return: """ data = { 'from': self.player.player_name, 'to': json_data['data']['to'], 'message': json_data['data']['message'] } try: self.send_to_spec_user(to_player=json_data['data']['to'], message=UtilityModule.generate_response( action=action, code=200, data=data)) except ChatExceptions.ChatException: self.send_one(response=UtilityModule.generate_response( action=action, code=407)) def send_chat_message(self, action: str, json_data: Any) -> None: """ Sending message to the cat from a specified player :param action: String used to generate response :param json_data: Received data from the client :return: """ data = { 'from': self.player.player_name, 'message': json_data['data']['message'] } self.send_all(message=UtilityModule.generate_response( action=action, code=200, data=data)) def send_all(self, message: bytes) -> None: """ Sending message to al authorized users :param message: Json object to send for all authorized users :return: """ self.log_to_debug(line=f"Send_All: {message}") for user_key in self.connected_users: if self.connected_users[user_key]['authorized']: protocol = self.connected_users[user_key]['main'][ 'base'].transport.protocol protocol.sendLine(line=message) def send_one(self, response: bytes) -> None: """ Send response from server :param response: :return: """ self.log_to_debug(line=f"Send_One: {response} ") self.sendLine(line=response) def send_to_spec_user(self, to_player: str, message: bytes) -> None: """ Send a message to specified user from user :param to_player: User whom to send :param message: Message to send :return: """ self.log_to_debug(line=f"Send_To_Spec: {message}") user_to_logged = False user_to_key = "" if self.cursor.check_player_name(name=to_player) == 1: for user_key in self.connected_users: if self.connected_users[user_key]['authorized'] \ and self.connected_users[user_key]['main']['player_name'] == to_player: user_to_logged = True user_to_key = user_key break else: raise ChatExceptions.ChatException("player not registered") if user_to_logged: self.sendLine(line=message) protocol = self.connected_users[user_to_key]['main'][ 'base'].transport.protocol protocol.sendLine(line=message) else: raise ChatExceptions.ChatException("player not logged")