Beispiel #1
0
    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")
Beispiel #6
0
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)
Beispiel #7
0
 def __init__(self):
     super(DBCore, self).__init__()
     self.log = Log(self.__class__)
Beispiel #8
0
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")