예제 #1
0
    def new_zone(self, areas: Set[AreaManager.Area],
                 watchers: Set[ClientManager.Client]) -> str:
        """
        Create a zone with the given area set and given watchers set and return its ID.

        Parameters
        ----------
        areas: set of AreaManager.Area
            Set of areas the zone covers.
        watchers: set of ClientManager.Client
            Set of clients who are watching the zone.

        Returns
        -------
        str
            The ID of the zone just created.

        Raises
        ------
        ZoneError.AreaConflictError:
            If one of the areas of the new zone already belongs to some other zone.
        ZoneError.WatcherConflictError:
            If one of the watchers of the new zone is already watching some other zone.
        """

        zone_id = self._generate_id()
        conflict_areas = self.areas_in_some_zone(areas)
        if conflict_areas:
            if len(conflict_areas) == 1:
                message = 'Area {} already belongs in a zone.'.format(
                    conflict_areas.pop())
            else:
                message = ('Areas {} already belong in a zone.'.format(
                    Constants.cjoin([area.id for area in conflict_areas])))
            raise ZoneError.AreaConflictError(message)

        conflict_watchers = self.watchers_in_some_zone(watchers)
        if conflict_watchers:
            if len(conflict_watchers) == 1:
                message = 'Watcher {} is already watching a zone.'.format(
                    conflict_watchers.pop())
            else:
                message = ('Watchers {} are already watching a zone.'.format(
                    Constants.cjoin(conflict_watchers)))
            raise ZoneError.WatcherConflictError(message)

        zone = self.Zone(self._server, zone_id, areas, watchers)
        self._zones[zone_id] = zone
        self._check_structure()
        return zone_id
예제 #2
0
        def add_areas(self, areas, check_structure=True):
            """
            Add a set of areas to the zone area set if ALL areas were not part of a zone already.

            This also sets the zone of the given areas to the current zone.

            Parameters
            ----------
            areas: set of AreaManager.Area
                Areas to add to the zone area set.
            check_structure: boolean, optional
                If set to False, the manager will skip the structural integrity test.

            Raises
            ------
            ZoneError.AreaConflictError:
                If any of the given areas is already a part of some zone area set.
            """

            for area in areas:
                if area.in_zone:
                    raise ZoneError.AreaConflictError(
                        'Area {} is already part of zone {}.'.format(
                            area, area.in_zone))

            for area in areas:
                self._areas.add(area)
                area.in_zone = self

            if check_structure:
                self._server.zone_manager._check_structure()
예제 #3
0
        def remove_watcher(self, watcher):
            """
            Remove a client from the zone watcher set if it was there.

            This also sets the watched zone of the client to None.

            Parameters
            ----------
            watcher: ClientManager.Client
                Watcher to remove from the zone watcher set.

            Raises
            ------
            ZoneError.WatcherNotInZoneError:
                If the watcher is not part of the zone watcher set.
            """

            if watcher not in self._watchers:
                raise ZoneError.WatcherNotInZoneError(
                    'Watcher {} is not watching zone {}.'.format(
                        watcher, self))

            self._watchers.remove(watcher)
            watcher.zone_watched = None

            # If no more watchers, delete the zone
            if not self._watchers:
                self._server.zone_manager.delete_zone(self._zone_id)
            self._server.zone_manager._check_structure()
예제 #4
0
        def add_watchers(self, watchers, check_structure=True):
            """
            Add a set of watchers to the zone watcher set if ALL watchers were not watching some
            zone already.

            This also sets the watched zone of the watchers to the current zone.

            Parameters
            ----------
            watcher: set of ClientManager.Client
                Watchers to add to the zone watcher set.
            check_structure: boolean, optional
                If set to False, the manager will skip the structural integrity test.

            Raises
            ------
            ZoneError.WatcherConflictError:
                If any of the given watchers is already watching some other zone
            """

            for watcher in watchers:
                if watcher.zone_watched:
                    raise ZoneError.WatcherConflictError(
                        'Watcher {} is already watching zone {}.'.format(
                            watcher, watcher.zone_watched))

            for watcher in watchers:
                self._watchers.add(watcher)
                watcher.zone_watched = self

            if check_structure:
                self._server.zone_manager._check_structure()
예제 #5
0
        def remove_area(self, area):
            """
            Remove an area from the zone area set if it was there.

            This also sets the zone of the given area to None.

            Parameters
            ----------
            area: AreaManager.Area
                Area to remove from the zone area set.

            Raises
            ------
            KeyError:
                If the area is not part of the zone area set.
            """

            if area not in self._areas:
                raise ZoneError.AreaNotInZoneError(
                    'Area {} is not part of zone {}.'.format(area, self))

            self._areas.remove(area)
            area.in_zone = None

            # If no more areas, delete the zone
            if not self._areas:
                self._server.zone_manager.delete_zone(self._zone_id)
            self._server.zone_manager._check_structure()
예제 #6
0
        def _add_watchers(self, users: Set[ClientManager.Client]):
            for user in users:
                if user.zone_watched:
                    raise ZoneError.WatcherConflictError(
                        'Watcher {} is already watching zone {}.'.format(
                            user, user.zone_watched))

            for user in users:
                self._watchers.add(user)
                user.zone_watched = self
예제 #7
0
        def _add_areas(self, areas: Set[AreaManager.Area]):
            for area in areas:
                if area.in_zone:
                    raise ZoneError.AreaConflictError(
                        'Area {} is already part of zone {}.'.format(
                            area, area.in_zone))

            for area in areas:
                self._areas.add(area)
                self.listener.subscribe(area)
                area.in_zone = self
                for client in area.clients:
                    self._add_player(client)
예제 #8
0
        def _add_player(self, user: ClientManager.Client):
            if user in self._players:
                raise ZoneError.PlayerConflictError(
                    'User is already a player in the zone.')
            if user.area not in self._areas:
                raise ZoneError.PlayerNotInZoneError(
                    'User is in an area not part of the zone.')

            self._players.add(user)
            self.listener.subscribe(user)

            user.send_gamemode(name=self.get_mode())

            if self.is_property('Handicap'):
                length, name, announce_if_over = self.get_property('Handicap')
                user.change_handicap(True,
                                     length=length,
                                     name=name,
                                     announce_if_over=announce_if_over)

            if self.is_property('Chat_tick_rate'):
                chat_tick_rate = self.get_property('Chat_tick_rate')
                user.send_chat_tick_rate(chat_tick_rate=chat_tick_rate)
예제 #9
0
        def _remove_area(self, area: AreaManager.Area):
            if area not in self._areas:
                raise ZoneError.AreaNotInZoneError(
                    'Area {} is not part of zone {}.'.format(area, self))

            self._areas.remove(area)
            self._cleanup_removed_area(area)

            for client in area.clients:
                self._remove_player(client)

            # If no more areas, delete the zone
            if not self._areas:
                self._server.zone_manager.delete_zone(self._zone_id)
예제 #10
0
        def _remove_player(self, user: ClientManager.Client):
            if user not in self._players:
                raise ZoneError.PlayerNotInZoneError(
                    'User {} is not a player of zone {}.'.format(user, self))

            self._players.remove(user)
            self._cleanup_removed_player(user)

            # If no more watchers nor players, delete the zone
            if not self._watchers and not self._players:
                self._server.zone_manager.delete_zone(self._zone_id)
                user.send_ooc(
                    '(X) Zone `{}` that you were in was automatically ended as no one '
                    'was in an area part of it or was watching it anymore.'.
                    format(self._zone_id),
                    is_staff=True)
                user.send_ooc_others(
                    'Zone `{}` was automatically ended as no one was in an '
                    'area part of it or was watching it anymore.'.format(
                        self._zone_id),
                    is_officer=True)
예제 #11
0
        def remove_property(self, property_name: str) -> Any:
            """
            Remove a previously set property of the zone.

            Parameters
            ----------
            property_name : str
                Property to remove.

            Returns
            -------
            Any
                Previously stored value of the property.

            Raises
            ------
            ZoneError.PropertyNotFoundError
                If the property to remove is already not a property.
            """

            try:
                return self._properties.pop(property_name)
            except KeyError:
                raise ZoneError.PropertyNotFoundError(property_name)
예제 #12
0
        def get_property(self, property_name: str) -> Any:
            """
            Return a previously set property of the zone.

            Parameters
            ----------
            property_name : str
                Property to fetch.

            Returns
            -------
            Any
                Stored value of the property.

            Raises
            ------
            ZoneError.PropertyNotFoundError
                If no such property was set for the zone.
            """

            try:
                return self._properties[property_name]
            except KeyError:
                raise ZoneError.PropertyNotFoundError(property_name)