Exemple #1
0
class TuxemonServer():
    """Server class for multiplayer games. Creates a netaria server and
    synchronizes the local game with all client states.

    :param game: instance of the local game.

    :type game: core.control.Control object.

    :rtype: None
    :returns: None

    """

    def __init__(self, game, server_name=None):

        self.game = game
        if not server_name:
            self.server_name = "Default Tuxemon Server"
        else:
            self.server_name = server_name
        self.network_events = []
        self.listening = False
        self.interfaces = {}
        self.ips = []

        # Handle users without networking support.
        if not networking:
            self.server = DummyNetworking()
            return

        self.server = NeteriaServer(Multiplayer(self), server_port=40081, server_name=self.server_name)


    def update(self):
        """Updates the server state with information sent from the clients

        :param None

        :type None

        :rtype: None
        :returns: None

        """
        self.server_timestamp = datetime.now()
        for cuuid in self.server.registry:
            try:
                difference = self.server_timestamp - self.server.registry[cuuid]["ping_timestamp"]
                if difference.seconds > 15:
                    logger.info("Client Disconnected. CUUID: " + str(cuuid))
                    event_data = {"type": "CLIENT_DISCONNECTED"}
                    self.notify_client(cuuid, event_data)
                    del self.server.registry[cuuid]
                    return False

            except KeyError:
                self.server.registry[cuuid]["ping_timestamp"] = datetime.now()




    def server_event_handler(self, cuuid, event_data):
        """Handles events sent from the middleware that are legal.

        :param cuuid: Clients unique user identification number.
        :param event_data: Event information sent by client.

        :type cuuid: String
        :type event_data: Dictionary

        :rtype: None
        :returns: None

        """
        # Only respond to the latest message of a given type
        if not "event_list" in self.server.registry[cuuid]:
            self.server.registry[cuuid]["event_list"] = {}
        elif not event_data["type"] in self.server.registry[cuuid]["event_list"]:
                self.server.registry[cuuid]["event_list"][event_data["type"]] = -1

        elif event_data["event_number"] <= self.server.registry[cuuid]["event_list"][event_data["type"]]:
            return False
        else:
            self.server.registry[cuuid]["event_list"][event_data["type"]] = event_data["event_number"]

        if event_data["type"] == "PUSH_SELF":
            self.server.registry[cuuid]["sprite_name"] = event_data["sprite_name"]
            self.server.registry[cuuid]["map_name"] = event_data["map_name"]
            self.server.registry[cuuid]["char_dict"] = event_data["char_dict"]
            self.server.registry[cuuid]["ping_timestamp"] = datetime.now()
            self.notify_populate_client(cuuid, event_data)

        elif event_data["type"] == "PING":
            self.server.registry[cuuid]["ping_timestamp"] = datetime.now()

        elif event_data["type"] == "CLIENT_INTERACTION" or event_data["type"] == "CLIENT_RESPONSE":
            self.notify_client_interaction(cuuid, event_data)

        elif event_data["type"] == "CLIENT_KEYDOWN":
            if event_data["kb_key"] == "SHIFT":
                self.server.registry[cuuid]["char_dict"]["running"] = True
                self.notify_client(cuuid, event_data)
            elif event_data["kb_key"] == "CTRL":
                self.notify_client(cuuid, event_data)
            elif event_data["kb_key"] == "ALT":
                self.notify_client(cuuid, event_data)

        elif event_data["type"] == "CLIENT_KEYUP":
            if event_data["kb_key"] == "SHIFT":
                self.server.registry[cuuid]["char_dict"]["running"] = False
                self.notify_client(cuuid, event_data)
            elif event_data["kb_key"] == "CTRL":
                self.notify_client(cuuid, event_data)
            elif event_data["kb_key"] == "ALT":
                self.notify_client(cuuid, event_data)

        elif event_data["type"] == "CLIENT_START_BATTLE":
            self.server.registry[cuuid]["char_dict"]["running"] = False
            self.update_char_dict(cuuid, event_data["char_dict"])
            self.server.registry[cuuid]["map_name"] = event_data["map_name"]
            self.notify_client(cuuid, event_data)

        else:
            self.update_char_dict(cuuid, event_data["char_dict"])
            if "map_name" in event_data:
                self.server.registry[cuuid]["map_name"] = event_data["map_name"]
            self.notify_client(cuuid, event_data)


    def update_char_dict(self, cuuid, char_dict):
        """Updates registry with player updates.

        :param cuuid: Clients unique user identification number.
        :param char_dict: character dictionary

        :type cuuid: String
        :type event_data: String

        :rtype: None
        :returns: None

        """
        for param in char_dict:
            self.server.registry[cuuid]["char_dict"][param] = char_dict[param]


    def notify_client(self, cuuid, event_data):
        """Updates all clients with player updates.

        :param cuuid: Clients unique user identification number.
        :param event_data: Notification flag information.

        :type cuuid: String
        :type event_data: String

        :rtype: None
        :returns: None

        """
        cuuid = str(cuuid)
        event_data["type"] = "NOTIFY_" + event_data["type"]
        event_data["cuuid"] = cuuid
        for client_id in self.server.registry:
            # Don't notify a player that they themselves moved.
            if client_id == cuuid: continue

            # Notify client of the players new position.
            elif client_id != cuuid:
                self.server.notify(client_id, event_data)


    def notify_populate_client(self, cuuid, event_data):
        """Updates all clients with the details of the new client.

        :param cuuid: Clients unique user identification number.
        :param event_data: Event information sent by client.

        :type cuuid: String
        :type event_data: Dictionary

        :rtype: None
        :returns: None

        """
        cuuid = str(cuuid)
        event_data["type"] = "NOTIFY_" + event_data["type"]
        event_data_1 = event_data
        for client_id in self.server.registry:
            # Don't notify a player that they themselves populated.
            if client_id == cuuid:continue

            elif client_id != cuuid:
                # Send the new client data to this client
                event_data_1["cuuid"] = cuuid
                self.server.notify(client_id, event_data_1)

                # Send this clients data to the new client
                char = self.server.registry[client_id]
                event_data_2 = {"type":event_data["type"],
                                "cuuid": client_id,
                                "event_number": event_data["event_number"],
                                "sprite_name": char["sprite_name"],
                                "map_name": char["map_name"],
                                "char_dict": char["char_dict"]
                                }
                self.server.notify(cuuid, event_data_2)


    def notify_client_interaction(self, cuuid, event_data):
        """Notify a client that another client has interacted with them.

        :param cuuid: Clients unique user identification number.
        :param event_data: Notification information.

        :type cuuid: String
        :type event_data: Dictionary

        :rtype: None
        :returns: None

        """
        cuuid = str(cuuid)
        event_data["type"] = "NOTIFY_" + event_data["type"]
        client_id = event_data["target"]
        event_data["target"] = cuuid
        self.server.notify(client_id, event_data)
Exemple #2
0
class TuxemonServer():
    """Server class for multiplayer games. Creates a netaria server and
    synchronizes the local game with all client states.

    :param game: instance of the local game.

    :type game: core.control.Control object.

    :rtype: None
    :returns: None

    """

    def __init__(self, game):


        self.game = game
        self.network_events = []
        self.listening = False
        self.interfaces = {}
        self.ips = []

        # Handle users without networking support.
        if not networking:
            self.server = DummyNetworking()
            return

        self.server = NeteriaServer(Multiplayer(self), server_port=40081)

        for device in netifaces.interfaces():
            interface = netifaces.ifaddresses(device)
            try:
                self.interfaces[device] = interface[netifaces.AF_INET][0]['addr']
            except KeyError:
                pass

        for interface in self.interfaces:
            ip = self.interfaces[interface]
            if ip == "127.0.0.1": continue
            else: self.ips.append(ip)


    def update(self):
        """Updates the server state with information sent from the clients

        :param None

        :type None

        :rtype: None
        :returns: None

        """
        pass


    def server_event_handler(self, cuuid, event_data):
        """Handles events sent from the middleware that are legal.

        :param cuuid: Clients unique user identification number.
        :param event_data: Event information sent by client.

        :type cuuid: String
        :type event_data: Dictionary

        :rtype: None
        :returns: None

        """
        # Only respond to the latest message of a given type
        if not "event_list" in self.server.registry[cuuid]:
            self.server.registry[cuuid]["event_list"] = {}
        elif not event_data["type"] in self.server.registry[cuuid]["event_list"]:
                self.server.registry[cuuid]["event_list"][event_data["type"]] = -1

        elif event_data["event_number"] <= self.server.registry[cuuid]["event_list"][event_data["type"]]:
            return False
        else:
            self.server.registry[cuuid]["event_list"][event_data["type"]] = event_data["event_number"]

        if event_data["type"] == "PUSH_SELF":
            self.server.registry[cuuid]["sprite_name"] = event_data["sprite_name"]
            self.server.registry[cuuid]["map_name"] = event_data["map_name"]
            self.server.registry[cuuid]["char_dict"] = event_data["char_dict"]
            self.notify_populate_client(cuuid, event_data)

        elif event_data["type"] == "CLIENT_INTERACTION" or event_data["type"] == "CLIENT_RESPONSE":
            self.notify_client_interaction(cuuid, event_data)

        elif event_data["type"] == "CLIENT_KEYDOWN":
            if event_data["kb_key"] == "SHIFT":
                self.server.registry[cuuid]["char_dict"]["running"] = True
                self.notify_client(cuuid, event_data)
            elif event_data["kb_key"] == "CRTL":
                pass
            elif event_data["kb_key"] == "ALT":
                pass

        elif event_data["type"] == "CLIENT_KEYUP":
            if event_data["kb_key"] == "SHIFT":
                self.server.registry[cuuid]["char_dict"]["running"] = False
                self.notify_client(cuuid, event_data)
            elif event_data["kb_key"] == "CRTL":
                pass
            elif event_data["kb_key"] == "ALT":
                pass

        else:
            self.update_char_dict(cuuid, event_data["char_dict"])
            if "map_name" in event_data:
                self.server.registry[cuuid]["map_name"] = event_data["map_name"]
            self.notify_client(cuuid, event_data)


    def update_char_dict(self, cuuid, char_dict):
        """Updates registry with player updates.

        :param cuuid: Clients unique user identification number.
        :param char_dict: character dictionary

        :type cuuid: String
        :type event_data: String

        :rtype: None
        :returns: None

        """
        for param in char_dict:
            self.server.registry[cuuid]["char_dict"][param] = char_dict[param]


    def notify_client(self, cuuid, event_data):
        """Updates all clients with player updates.

        :param cuuid: Clients unique user identification number.
        :param event_data: Notification flag information.

        :type cuuid: String
        :type event_data: String

        :rtype: None
        :returns: None

        """
        cuuid = str(cuuid)
        event_data["type"] = "NOTIFY_" + event_data["type"]
        event_data["cuuid"] = cuuid
        for client_id in self.server.registry:
            # Don't notify a player that they themselves moved.
            if client_id == cuuid: continue

            # Notify client of the players new position.
            elif client_id != cuuid:
                self.server.notify(client_id, event_data)


    def notify_populate_client(self, cuuid, event_data):
        """Updates all clients with the details of the new client.

        :param cuuid: Clients unique user identification number.
        :param event_data: Event information sent by client.

        :type cuuid: String
        :type event_data: Dictionary

        :rtype: None
        :returns: None

        """
        cuuid = str(cuuid)
        event_data["type"] = "NOTIFY_" + event_data["type"]
        event_data_1 = event_data
        for client_id in self.server.registry:
            # Don't notify a player that they themselves populated.
            if client_id == cuuid:continue

            elif client_id != cuuid:
                # Send the new client data to this client
                event_data_1["cuuid"] = cuuid
                self.server.notify(client_id, event_data_1)

                # Send this clients data to the new client
                char = self.server.registry[client_id]
                event_data_2 = {"type":event_data["type"],
                                "cuuid": client_id,
                                "event_number": event_data["event_number"],
                                "sprite_name": char["sprite_name"],
                                "map_name": char["map_name"],
                                "char_dict": char["char_dict"]
                                }
                self.server.notify(cuuid, event_data_2)


    def notify_client_interaction(self, cuuid, event_data):
        """Notify a client that another client has interacted with them.

        :param cuuid: Clients unique user identification number.
        :param event_data: Notification information.

        :type cuuid: String
        :type event_data: Dictionary

        :rtype: None
        :returns: None

        """
        cuuid = str(cuuid)
        event_data["type"] = "NOTIFY_" + event_data["type"]
        client_id = event_data["target"]
        event_data["target"] = cuuid
        self.server.notify(client_id, event_data)