Пример #1
0
    def _show_skin_in_model_viewer(self, row):
        skin_name = self.proxy.data(self.proxy.index(row, 0))
        ac_name = self.proxy.data(self.proxy.index(row, 1))
        mv_autoexec_cfg = Path(self._active_dcs_install.install_path).joinpath(
            'Config', 'ModelViewer', 'autoexec.lua')
        mv_exe = Path(self._active_dcs_install.install_path).joinpath(
            'bin', 'ModelViewer.exe')

        for f in mv_autoexec_cfg, mv_exe:
            if not f.exists():
                logger.error('file not found: {}'.format(f.abspath()))
                return

        mount_lines = set()
        if self._active_dcs_install.autoexec_cfg:
            for vfs_path in self._active_dcs_install.autoexec_cfg.mounted_vfs_paths:
                mount_lines.add(
                    'mount_vfs_texture_path("{}")\n'.format(vfs_path))

        backup_path = mv_autoexec_cfg.dirname().joinpath(
            'autoexec.lua_EMFT_BACKUP')
        if not backup_path.exists():
            logger.info('backing up "{}" -> "{}"'.format(
                mv_autoexec_cfg.abspath(), backup_path.abspath()))
            mv_autoexec_cfg.copy2(backup_path.abspath())

        orig_lines = mv_autoexec_cfg.lines()

        lines = []

        for line in orig_lines:
            if Config().allow_mv_autoexec_changes:
                if RE_MOUNT_LINE.match(line):
                    # print('skipping', line)
                    continue
            if RE_LOAD_MODEL_LINE.match(line):
                # print('skipping', line)
                continue
            if RE_LOAD_LIVERY_LINE.match(line):
                # print('skipping', line)
                continue
            lines.append(line)

        # model_path = 'LoadModel("Bazar/World/Shapes/{}.edm")'.format(self._active_dcs_install.get_object_model(ac_name))

        lines.insert(
            0, 'LoadLivery("{ac_name}","{skin_name}")'.format(**locals()))
        lines.insert(
            0,
            'LoadModel("Bazar/World/Shapes/{ac_name}.edm")'.format(**locals()))

        if Config().allow_mv_autoexec_changes:
            for line in mount_lines:
                lines.insert(0, line)

        mv_autoexec_cfg.write_lines(lines)

        os.startfile(mv_exe.abspath())
Пример #2
0
class Miz:
    def __init__(self, path_to_miz_file, temp_dir=None, keep_temp_dir: bool = False):

        self.miz_path = Path(path_to_miz_file)

        if not self.miz_path.exists():
            raise FileNotFoundError(path_to_miz_file)

        if not self.miz_path.isfile():
            raise TypeError(path_to_miz_file)

        if not self.miz_path.ext == '.miz':
            raise ValueError(path_to_miz_file)

        if temp_dir is not None:
            raise PendingDeprecationWarning()

        self.keep_temp_dir = keep_temp_dir

        self.tmpdir = Path(tempfile.mkdtemp('EMFT_'))
        logger.debug('temporary directory: {}'.format(self.tmpdir.abspath()))

        self.zip_content = None
        self._mission = None
        self._mission_qual = None
        self._l10n = None
        self._l10n_qual = None
        self._map_res = None
        self._map_res_qual = None

    def __enter__(self):
        logger.debug('instantiating new Mission object as a context')
        self.unzip()
        self._decode()
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        if exc_type:
            logger.error('there were error with this mission, keeping temp dir at "{}" and re-raising'.format(
                self.tmpdir.abspath()))
            logger.error('{}\n{}'.format(exc_type, exc_val))
            return False
        else:
            logger.debug('closing Mission object context')
            if not self.keep_temp_dir:
                logger.debug('removing temp dir: {}'.format(self.tmpdir.abspath()))
                self.tmpdir.rmtree()

    @property
    def mission_file(self):
        return self.tmpdir.joinpath('mission')

    @property
    def dictionary_file(self):
        return self.tmpdir.joinpath('l10n', 'DEFAULT', 'dictionary')

    @property
    def map_res_file(self):
        return self.tmpdir.joinpath('l10n', 'DEFAULT', 'mapResource')

    @property
    def mission(self) -> Mission:
        if self._mission is None:
            raise RuntimeError()
        return self._mission

    @property
    def l10n(self) -> dict:
        if self._l10n is None:
            raise RuntimeError()
        return self._l10n

    @property
    def map_res(self) -> dict:
        if self._map_res is None:
            raise RuntimeError()
        return self._map_res

    @staticmethod
    def reorder(miz_file_path, target_dir, skip_options_file):
        with Miz(miz_file_path) as m:

            def mirror_dir(src, dst):
                logger.debug('{} -> {}'.format(src, dst))
                diff_ = dircmp(src, dst, ignore)
                diff_list = diff_.left_only + diff_.diff_files
                logger.debug('differences: {}'.format(diff_list))
                for x in diff_list:
                    source = Path(diff_.left).joinpath(x)
                    target = Path(diff_.right).joinpath(x)
                    logger.debug('looking at: {}'.format(x))
                    if source.isdir():
                        logger.debug('isdir: {}'.format(x))
                        if not target.exists():
                            logger.debug('creating: {}'.format(x))
                            target.mkdir()
                        mirror_dir(source, target)
                    else:
                        logger.debug('copying: {}'.format(x))
                        source.copy2(diff_.right)
                for sub in diff_.subdirs.values():
                    assert isinstance(sub, dircmp)
                    mirror_dir(sub.left, sub.right)

            m.unzip(overwrite=True)
            m._decode()
            m._encode()

            if skip_options_file:
                ignore = ['options']
            else:
                ignore = []

            mirror_dir(m.tmpdir, target_dir)

    def _decode(self):

        logger.info('decoding lua tables')

        if not self.zip_content:
            self.unzip(overwrite=False)

        Progress.start('Decoding MIZ file', length=3)

        Progress.set_label('Decoding map resource')
        logger.debug('reading map resource file')
        with open(self.map_res_file, encoding=ENCODING) as f:
            self._map_res, self._map_res_qual = SLTP().decode(f.read())
        Progress.set_value(1)

        Progress.set_label('Decoding dictionary file')
        logger.debug('reading l10n file')
        with open(self.dictionary_file, encoding=ENCODING) as f:
            self._l10n, self._l10n_qual = SLTP().decode(f.read())
        Progress.set_value(2)

        Progress.set_label('Decoding mission file')
        logger.debug('reading mission file')
        with open(self.mission_file, encoding=ENCODING) as f:
            mission_data, self._mission_qual = SLTP().decode(f.read())
            self._mission = Mission(mission_data, self._l10n)
        Progress.set_value(3)

        logger.info('decoding done')

    def _encode(self):

        logger.info('encoding lua tables')

        Progress.start('Decoding MIZ file', length=3)

        Progress.set_label('Encoding map resource')
        logger.debug('encoding map resource')
        with open(self.map_res_file, mode='w', encoding=ENCODING) as f:
            f.write(SLTP().encode(self._map_res, self._map_res_qual))
        Progress.set_value(1)

        Progress.set_label('Encoding map resource')
        logger.debug('encoding l10n dictionary')
        with open(self.dictionary_file, mode='w', encoding=ENCODING) as f:
            f.write(SLTP().encode(self.l10n, self._l10n_qual))
        Progress.set_value(2)

        Progress.set_label('Encoding map resource')
        logger.debug('encoding mission dictionary')
        with open(self.mission_file, mode='w', encoding=ENCODING) as f:
            f.write(SLTP().encode(self.mission.d, self._mission_qual))
        Progress.set_value(3)

        logger.info('encoding done')

    def unzip(self, overwrite: bool = False):

        if self.zip_content and not overwrite:
            raise FileExistsError(self.tmpdir.abspath())

        logger.debug('unzipping miz to temp dir')

        try:

            with ZipFile(self.miz_path.abspath()) as zip_file:

                logger.debug('reading infolist')

                self.zip_content = [f.filename for f in zip_file.infolist()]

                for item in zip_file.infolist():  # not using ZipFile.extractall() for security reasons
                    assert isinstance(item, ZipInfo)

                    logger.debug('unzipping item: {}'.format(item))

                    try:
                        zip_file.extract(item, self.tmpdir.abspath())
                    except:
                        logger.error('failed to extract archive member: {}'.format(item))
                        raise

        except BadZipFile:
            raise BadZipFile(self.miz_path.abspath())

        except:
            logger.exception('error while unzipping miz file: {}'.format(self.miz_path.abspath()))
            raise

        logger.debug('checking miz content')

        # noinspection PyTypeChecker
        for miz_item in map(
                join,
                [self.tmpdir.abspath()],
                [
                    'mission',
                    'options',
                    'warehouses',
                    'l10n/DEFAULT/dictionary',
                    'l10n/DEFAULT/mapResource'
                ]):

            if not exists(miz_item):
                logger.error('missing file in miz: {}'.format(miz_item))
                raise FileNotFoundError(miz_item)

        for filename in self.zip_content:
            p = self.tmpdir.joinpath(filename)
            if not p.exists():
                raise FileNotFoundError(p.abspath())

        logger.debug('all files have been found, miz successfully unzipped')

    def zip(self, destination=None):

        self._encode()

        if destination is None:
            destination = Path(self.miz_path.dirname()).joinpath('{}_EMFT.miz'.format(self.miz_path.namebase))

        destination = Path(destination).abspath()

        logger.debug('zipping mission to: {}'.format(destination))

        with open(destination, mode='wb') as f:
            f.write(dummy_miz)

        with ZipFile(destination, mode='w', compression=8) as _z:

            for f in self.zip_content:
                abs_path = self.tmpdir.joinpath(f).abspath()
                logger.debug('injecting in zip file: {}'.format(abs_path))
                _z.write(abs_path, arcname=f)

        return destination