Пример #1
0
        def __init__(self, area_id, server, parameters):
            """
            Parameters
            ----------
            area_id: int
                The area ID.
            server: server.TsuserverDR
                The server this area belongs to.
            parameters: dict
                Area parameters as specified in the loaded area list.
            """

            self.clients = set()
            self.invite_list = {}
            self.id = area_id
            self.server = server
            self.music_looper = None
            self.next_message_time = 0
            self.hp_def = 10
            self.hp_pro = 10
            self.doc = 'No document.'
            self.status = 'IDLE'
            self.judgelog = []
            self.shoutlog = []
            self.current_music = ''
            self.current_music_player = ''
            self.evi_list = EvidenceList()
            self.is_recording = False
            self.recorded_messages = []
            self.owned = False
            self.ic_lock = False
            self.is_locked = False
            self.is_gmlocked = False
            self.is_modlocked = False
            self.bleeds_to = set()
            self.blood_smeared = False
            self.lights = True
            self.last_ic_messages = list()
            self.parties = set()
            self.dicelog = list()
            self._in_zone = None

            self.name = parameters['area']
            self.background = parameters['background']
            self.bg_lock = parameters['bglock']
            self.evidence_mod = parameters['evidence_mod']
            self.locking_allowed = parameters['locking_allowed']
            self.iniswap_allowed = parameters['iniswap_allowed']
            self.rp_getarea_allowed = parameters['rp_getarea_allowed']
            self.rp_getareas_allowed = parameters['rp_getareas_allowed']
            self.rollp_allowed = parameters['rollp_allowed']
            self.reachable_areas = parameters['reachable_areas']
            self.change_reachability_allowed = parameters[
                'change_reachability_allowed']
            self.default_change_reachability_allowed = parameters[
                'change_reachability_allowed']
            self.gm_iclock_allowed = parameters['gm_iclock_allowed']
            self.afk_delay = parameters['afk_delay']
            self.afk_sendto = parameters['afk_sendto']
            self.lobby_area = parameters['lobby_area']
            self.private_area = parameters['private_area']
            self.scream_range = parameters['scream_range']
            self.restricted_chars = parameters['restricted_chars']
            self.default_description = parameters['default_description']
            self.has_lights = parameters['has_lights']
            self.cbg_allowed = parameters['cbg_allowed']
            self.song_switch_allowed = parameters['song_switch_allowed']
            self.bullet = parameters['bullet']

            # Store the current description separately from the default description
            self.description = self.default_description
            # Have a background backup in order to restore temporary background changes
            self.background_backup = self.background
            # Fix comma-separated entries
            self.reachable_areas = Constants.fix_and_setify(
                self.reachable_areas)
            self.scream_range = Constants.fix_and_setify(self.scream_range)
            self.restricted_chars = Constants.fix_and_setify(
                self.restricted_chars)

            self.default_reachable_areas = self.reachable_areas.copy()
            self.staffset_reachable_areas = self.reachable_areas.copy()

            if '<ALL>' not in self.reachable_areas:
                self.reachable_areas.add(self.name)  # Safety feature, yay sets

            # Make sure only characters that exist are part of the restricted char set
            try:
                for char_name in self.restricted_chars:
                    self.server.char_list.index(char_name)
            except ValueError:
                info = (
                    'Area `{}` has a character `{}` not in the character list of the server '
                    'listed as a restricted character. Please make sure this character exists '
                    'and try again.'.format(self.name, char_name))
                raise AreaError(info)
Пример #2
0
    def validate_contents(self, contents, extra_parameters=None):
        if extra_parameters is None:
            extra_parameters = dict()
        server_character_list = extra_parameters.get('server_character_list',
                                                     None)
        server_default_area_description = extra_parameters.get(
            'server_default_area_description', '')

        default_area_parameters = {
            'afk_delay': 0,
            'afk_sendto': 0,
            'background_tod': dict(),
            'bglock': False,
            'bullet': True,
            'cbg_allowed': False,
            'change_reachability_allowed': True,
            'default_description': server_default_area_description,
            'evidence_mod': 'FFA',
            'gm_iclock_allowed': True,
            'has_lights': True,
            'iniswap_allowed': False,
            'global_allowed': True,
            'lobby_area': False,
            'locking_allowed': False,
            'private_area': False,
            'reachable_areas': '<ALL>',
            'restricted_chars': '',
            'rollp_allowed': True,
            'rp_getarea_allowed': True,
            'rp_getareas_allowed': True,
            'scream_range': '',
            'song_switch_allowed': False,
        }

        current_area_id = 0
        area_parameters = list()
        temp_area_names = set()
        found_uncheckable_restricted_chars = False

        # Create the areas
        for item in contents:
            # Check required parameters
            if 'area' not in item:
                info = 'Area {} has no name.'.format(current_area_id)
                raise AreaError(info)
            if 'background' not in item:
                info = 'Area {} has no background.'.format(item['area'])
                raise AreaError(info)

            # Prevent reserved area names (it has a special meaning)
            reserved_names = {
                '<ALL>',
                '<REACHABLE_AREAS>',
            }

            for name in reserved_names:
                if item['area'] == name:
                    info = (
                        'An area in your area list is called "{name}". This is a reserved '
                        'name, so it is not a valid area name. Please change its name and try '
                        'again.')
                    raise AreaError(info)

            # Prevent names that may be interpreted as a directory with . or ..
            # This prevents sending the client an entry to their music list which may be read as
            # including a relative directory
            if Constants.includes_relative_directories(item['area']):
                info = (
                    f'Area {item["area"]} could be interpreted as referencing the current or '
                    f'parent directories, so it is invalid. Please rename the area and try '
                    f'again.')
                raise AreaError(info)

            # Check unset optional parameters
            for param in default_area_parameters:
                if param not in item:
                    item[param] = default_area_parameters[param]

            # Check use of backwards incompatible parameters
            if 'sound_proof' in item:
                info = (
                    'The sound_proof property was defined for area {}. '
                    'Support for sound_proof was removed in favor of scream_range. '
                    'Please replace the sound_proof tag with scream_range in '
                    'your area list and try again.'.format(item['area']))
                raise AreaError(info)

            # Avoid having areas with the same name
            if item['area'] in temp_area_names:
                info = (
                    'Two areas have the same name in area list: {}. '
                    'Please rename the duplicated areas and try again.'.format(
                        item['area']))
                raise AreaError(info)

            # Check if any of the items were interpreted as Python Nones (maybe due to empty lines)
            for parameter in item:
                if item[parameter] is None:
                    info = (
                        'Parameter {} is manually undefined for area {}. This can be the case '
                        'due to having an empty parameter line in your area list. '
                        'Please fix or remove the parameter from the area definition and try '
                        'again.'.format(parameter, item['area']))
                    raise AreaError(info)

            # Check and fix background tods if needed, as YAML parses this as a list of
            if item['background_tod'] != dict():
                raw_background_tod_map = item['background_tod']
                if not isinstance(raw_background_tod_map, dict):
                    info = (
                        f'Expected background TOD for area {item["area"]} be '
                        f'one dictionary, found it was of type '
                        f'{type(raw_background_tod_map).__name__}: {raw_background_tod_map}'
                    )
                    raise AreaError(info)

                new_background_tod = dict()
                if not isinstance(raw_background_tod_map, dict):
                    info = (
                        f'Expected background TOD for area {item["area"]} be a dictionary, '
                        f'found it was of type {type(raw_background_tod_map).__name__}: '
                        f'{raw_background_tod_map}')
                    raise AreaError(info)

                for (key, value) in raw_background_tod_map.items():
                    tod_name = str(key)
                    tod_background = str(value)
                    if not tod_name.strip():
                        info = (
                            f'TOD name `{tod_name}` invalid for area {item["area"]}. '
                            f'Make sure the TOD name has non-space characters and try '
                            f'again.')
                        raise AreaError(info)
                    if ' ' in tod_name:
                        info = (
                            f'TOD name `{tod_name}` invalid for area {item["area"]}. '
                            f'Make sure the TOD name has no space characters and try '
                            f'again.')
                        raise AreaError(info)
                    if '|' in tod_name:
                        info = (
                            f'TOD name `{tod_name}` contains invalid character |.'
                            f'Make sure the TOD name does not have that character and '
                            f'try again.')
                        raise AreaError(info)
                    if '|' in tod_background:
                        info = (
                            f'TOD background `{tod_background}` contains invalid '
                            f'character |. Make sure the TOD name does not have that '
                            f'character and try again.')
                        raise AreaError(tod_background)

                    new_background_tod[tod_name] = tod_background
                item['background_tod'] = new_background_tod

            area_parameters.append(item.copy())
            temp_area_names.add(item['area'])
            current_area_id += 1

        # Check if a reachable area is not an area name
        # Can only be done once all areas are created
        for area_item in area_parameters:
            name = area_item['area']

            reachable_areas = Constants.fix_and_setify(
                area_item['reachable_areas'])
            scream_range = Constants.fix_and_setify(area_item['scream_range'])
            restricted_chars = Constants.fix_and_setify(
                area_item['restricted_chars'])

            if reachable_areas == {'<ALL>'}:
                reachable_areas = temp_area_names.copy()
            if scream_range == {'<ALL>'}:
                scream_range = temp_area_names.copy()
            elif scream_range == {'<REACHABLE_AREAS>'}:
                scream_range = reachable_areas.copy()

            area_item['reachable_areas'] = reachable_areas
            area_item['scream_range'] = scream_range
            area_item['restricted_chars'] = restricted_chars

            # Make sure no weird areas were set as reachable by players or by screams
            unrecognized_areas = reachable_areas - temp_area_names
            if unrecognized_areas:
                info = (
                    f'Area {name} has unrecognized areas {unrecognized_areas} defined as '
                    f'areas a player can reach to. Please rename the affected areas and try '
                    f'again.')
                raise AreaError(info)

            unrecognized_areas = scream_range - temp_area_names
            if unrecognized_areas:
                info = (
                    f'Area {name} has unrecognized areas {unrecognized_areas} defined as '
                    f'areas screams can reach to. Please rename the affected areas and try '
                    f'again.')
                raise AreaError(info)

            # Make sure only characters that exist are part of the restricted char set
            if server_character_list is not None:
                unrecognized_characters = restricted_chars - set(
                    server_character_list)
                if unrecognized_characters:
                    info = (
                        f'Area {name} has unrecognized characters {unrecognized_characters} '
                        f'defined as restricted characters. Please make sure the characters '
                        f'exist and try again.')
                    raise AreaError(info)
            elif restricted_chars:
                found_uncheckable_restricted_chars = True

        if found_uncheckable_restricted_chars:
            info = (
                'WARNING: Some areas provided default restricted characters. However, no '
                'server character list was provided, so no checks whether restricted '
                'characters were in the character list of the server were performed.'
            )
            print(info)

        return area_parameters