Example #1
0
 def __init__(
     self,
     quote_id,
     selitem_data: 'SelitemData',
     config: Property,
     chars: Optional[Set[str]] = None,
     skin: Optional[int] = None,
     studio: str = None,
     studio_actor: str = '',
     cam_loc: Vec = None,
     turret_hate: bool = False,
     interrupt: float = 0.0,
     cam_pitch: float = 0.0,
     cam_yaw: float = 0.0,
 ) -> None:
     self.id = quote_id
     self.selitem_data = selitem_data
     self.cave_skin = skin
     self.config = config
     set_cond_source(config, 'QuotePack <{}>'.format(quote_id))
     self.chars = chars or {'??'}
     self.studio = studio
     self.studio_actor = studio_actor
     self.cam_loc = cam_loc
     self.inter_chance = interrupt
     self.cam_pitch = cam_pitch
     self.cam_yaw = cam_yaw
     self.turret_hate = turret_hate
Example #2
0
    def __init__(
            self,
            music_id,
            selitem_data: 'SelitemData',
            sound: Dict[MusicChannel, List[str]],
            children: Dict[MusicChannel, str],
            config: Property = None,
            inst=None,
            sample: Dict[MusicChannel, Optional[str]] = None,
            pack=(),
            loop_len=0,
            synch_tbeam=False,
    ):
        self.id = music_id
        self.config = config or Property(None, [])
        self.children = children
        set_cond_source(config, 'Music <{}>'.format(music_id))
        self.inst = inst
        self.sound = sound
        self.packfiles = list(pack)
        self.len = loop_len
        self.sample = sample

        self.selitem_data = selitem_data

        self.has_synced_tbeam = synch_tbeam
Example #3
0
	def loader() -> Property:
		"""Load and parse the specified file when called."""
		try:
			with file.open_str() as f:
				props = Property.parse(f)
		except (KeyValError, FileNotFoundError, UnicodeDecodeError):
			LOGGER.exception('Unable to read "{}"', path)
			raise
		if source:
			packages.set_cond_source(props, source)
		return props
Example #4
0
    def __init__(
        self,
        sky_id,
        selitem_data: SelitemData,
        config: Property,
        fog_opts: Property,
        mat,
    ) -> None:
        self.id = sky_id
        self.selitem_data = selitem_data
        self.material = mat
        self.config = config
        set_cond_source(config, 'Skybox <{}>'.format(sky_id))
        self.fog_opts = fog_opts

        # Extract this for selector windows to easily display
        self.fog_color = fog_opts.vec('primarycolor', 255, 255, 255)
Example #5
0
    def parse(cls, data: ParseData):
        """Parse from config files."""
        filesystem = data.fsys  # type: FileSystem
        vers = {}

        all_config = get_config(
            data.info,
            data.fsys,
            'items',
            pak_id=data.pak_id,
            prop_name='all_conf',
        )
        set_cond_source(
            all_config, '<ItemConfig {}:{} all_conf>'.format(
                data.pak_id,
                data.id,
            ))

        with filesystem:
            for ver in data.info.find_all('Version'):  # type: Property
                ver_id = ver['ID', 'VER_DEFAULT']
                vers[ver_id] = styles = {}
                for sty_block in ver.find_all('Styles'):
                    for style in sty_block:
                        styles[style.real_name] = conf = filesystem.read_prop(
                            'items/' + style.value + '.cfg')

                        set_cond_source(
                            conf, "<ItemConfig {}:{} in '{}'>".format(
                                data.pak_id,
                                data.id,
                                style.real_name,
                            ))

        return cls(
            data.id,
            all_config,
            vers,
        )
Example #6
0
			def copier() -> Property:
				"""Copy the config, then apply the source."""
				copy = block.copy()
				packages.set_cond_source(copy, source)
				return copy
Example #7
0
def parse_item_folder(
    folders_to_parse: Set[str],
    filesystem: FileSystem,
    pak_id: str,
) -> Dict[str, ItemVariant]:
    """Parse through the data in item/ folders.

    folders is a dict, with the keys set to the folder names we want.
    The values will be filled in with itemVariant values
    """
    folders: Dict[str, ItemVariant] = {}
    for fold in folders_to_parse:
        prop_path = 'items/' + fold + '/properties.txt'
        editor_path = 'items/' + fold + '/editoritems.txt'
        config_path = 'items/' + fold + '/vbsp_config.cfg'

        first_item: Optional[Item] = None
        extra_items: List[EditorItem] = []
        with filesystem:
            try:
                props = filesystem.read_prop(prop_path).find_key('Properties')
                f = filesystem[editor_path].open_str()
            except FileNotFoundError as err:
                raise IOError('"' + pak_id + ':items/' + fold + '" not valid!'
                              'Folder likely missing! ') from err
            with f:
                tok = Tokenizer(f, editor_path)
                for tok_type, tok_value in tok:
                    if tok_type is Token.STRING:
                        if tok_value.casefold() != 'item':
                            raise tok.error('Unknown item option "{}"!',
                                            tok_value)
                        if first_item is None:
                            first_item = EditorItem.parse_one(tok)
                        else:
                            extra_items.append(EditorItem.parse_one(tok))
                    elif tok_type is not Token.NEWLINE:
                        raise tok.error(tok_type)

        if first_item is None:
            raise ValueError('"{}:items/{}/editoritems.txt has no '
                             '"Item" block!'.format(pak_id, fold))

        # extra_items is any extra blocks (offset catchers, extent items).
        # These must not have a palette section - it'll override any the user
        # chooses.
        for extra_item in extra_items:
            for subtype in extra_item.subtypes:
                if subtype.pal_pos is not None:
                    LOGGER.warning(
                        '"{}:items/{}/editoritems.txt has palette set for extra'
                        ' item blocks. Deleting.'.format(pak_id, fold))
                    subtype.pal_icon = subtype.pal_pos = subtype.pal_name = None

        try:
            all_icon = FSPath(props['all_icon'])
        except LookupError:
            all_icon = None

        folders[fold] = ItemVariant(
            editoritems=first_item,
            editor_extra=extra_items,

            # Add the folder the item definition comes from,
            # so we can trace it later for debug messages.
            source='<{}>/items/{}'.format(pak_id, fold),
            vbsp_config=Property(None, []),
            authors=sep_values(props['authors', '']),
            tags=sep_values(props['tags', '']),
            desc=desc_parse(props, pak_id + ':' + prop_path),
            ent_count=props['ent_count', ''],
            url=props['infoURL', None],
            icons={p.name: p.value
                   for p in props['icon', []]},
            all_name=props['all_name', None],
            all_icon=all_icon,
        )

        if Item.log_ent_count and not folders[fold].ent_count:
            LOGGER.warning(
                '"{id}:{path}" has missing entity count!',
                id=pak_id,
                path=prop_path,
            )

        # If we have at least 1, but not all of the grouping icon
        # definitions then notify the author.
        num_group_parts = ((folders[fold].all_name is not None) +
                           (folders[fold].all_icon is not None) +
                           ('all' in folders[fold].icons))
        if 0 < num_group_parts < 3:
            LOGGER.warning(
                'Warning: "{id}:{path}" has incomplete grouping icon '
                'definition!',
                id=pak_id,
                path=prop_path,
            )
        try:
            with filesystem:
                folders[fold].vbsp_config = conf = filesystem.read_prop(
                    config_path, )
        except FileNotFoundError:
            folders[fold].vbsp_config = conf = Property(None, [])

        set_cond_source(conf, folders[fold].source)
    return folders
Example #8
0
    def parse(cls, data: ParseData):
        """Parse an item definition."""
        versions: Dict[str, Version] = {}
        def_version: Optional[Version] = None
        # The folders we parse for this - we don't want to parse the same
        # one twice.
        folders_to_parse: Set[str] = set()
        unstyled = data.info.bool('unstyled')

        glob_desc = desc_parse(data.info, 'global:' + data.id)
        desc_last = data.info.bool('AllDescLast')

        all_config = get_config(
            data.info,
            data.fsys,
            'items',
            pak_id=data.pak_id,
            prop_name='all_conf',
        )
        set_cond_source(all_config, '<Item {} all_conf>'.format(data.id, ))

        for ver in data.info.find_all('version'):
            ver_name = ver['name', 'Regular']
            ver_id = ver['ID', 'VER_DEFAULT']
            styles: Dict[str, ItemVariant] = {}
            ver_isolate = ver.bool('isolated')
            def_style = None

            for style in ver.find_children('styles'):
                if style.has_children():
                    folder = UnParsedItemVariant(
                        data.fsys,
                        folder=style['folder', None],
                        style=style['Base', ''],
                        config=style,
                    )

                elif style.value.startswith('<') and style.value.endswith('>'):
                    # Reusing another style unaltered using <>.
                    folder = UnParsedItemVariant(
                        data.fsys,
                        style=style.value[1:-1],
                        folder=None,
                        config=None,
                    )
                else:
                    # Reference to the actual folder...
                    folder = UnParsedItemVariant(
                        data.fsys,
                        folder=style.value,
                        style=None,
                        config=None,
                    )
                # We need to parse the folder now if set.
                if folder.folder:
                    folders_to_parse.add(folder.folder)

                # The first style is considered the 'default', and is used
                # if not otherwise present.
                # We set it to the name, then lookup later in setup_style_tree()
                if def_style is None:
                    def_style = style.real_name
                # It'll only be UnParsed during our parsing.
                styles[style.real_name] = cast(ItemVariant, folder)

                if style.real_name == folder.style:
                    raise ValueError('Item "{}"\'s "{}" style '
                                     'can\'t inherit from itself!'.format(
                                         data.id,
                                         style.real_name,
                                     ))
            versions[ver_id] = version = Version(
                ver_id,
                ver_name,
                ver_isolate,
                styles,
                def_style,
            )

            # The first version is the 'default',
            # so non-isolated versions will fallback to it.
            # But the default is isolated itself.
            if def_version is None:
                def_version = version
                version.isolate = True

        if def_version is None:
            raise ValueError(f'Item "{data.id}" has no versions!')

        # Fill out the folders dict with the actual data
        parsed_folders = parse_item_folder(folders_to_parse, data.fsys,
                                           data.pak_id)

        # We want to ensure the number of visible subtypes doesn't change.
        subtype_counts = {
            tuple([
                i for i, subtype in enumerate(folder.editor.subtypes, 1)
                if subtype.pal_pos or subtype.pal_name
            ])
            for folder in parsed_folders.values()
        }
        if len(subtype_counts) > 1:
            raise ValueError(
                f'Item "{data.id}" has different '
                f'visible subtypes in its styles: {", ".join(map(str, subtype_counts))}'
            )

        # Then copy over to the styles values
        for ver in versions.values():
            if isinstance(ver.def_style, str):
                try:
                    ver.def_style = parsed_folders[ver.def_style]
                except KeyError:
                    pass
            for sty, fold in ver.styles.items():
                if isinstance(fold, str):
                    ver.styles[sty] = parsed_folders[fold]

        return cls(
            data.id,
            versions=versions,
            def_version=def_version,
            needs_unlock=data.info.bool('needsUnlock'),
            isolate_versions=data.info.bool('isolate_versions'),
            all_conf=all_config,
            unstyled=unstyled,
            glob_desc=glob_desc,
            desc_last=desc_last,
            # Add filesystem to individualise this to the package.
            folders={(data.fsys, folder): item_variant
                     for folder, item_variant in parsed_folders.items()})