示例#1
0
def find_modded_files(
    tmp_dir: Path,
    pool: Optional[multiprocessing.pool.Pool] = None
) -> List[Union[Path, str]]:
    modded_files = []
    if isinstance(tmp_dir, str):
        tmp_dir = Path(tmp_dir)

    if (tmp_dir / util.get_dlc_path()).exists():
        try:
            util.get_aoc_dir()
        except FileNotFoundError:
            raise FileNotFoundError(
                "This mod uses DLC files, but BCML cannot locate the DLC folder in "
                "your game dump.")

    aoc_field = (tmp_dir / util.get_dlc_path() /
                 ("0010" if util.get_settings("wiiu") else "") / "Pack" /
                 "AocMainField.pack")
    if aoc_field.exists() and aoc_field.stat().st_size > 0:
        if not list((tmp_dir / util.get_dlc_path() /
                     ("0010" if util.get_settings("wiiu") else "")
                     ).rglob("Map/**/?-?_*.smubin")):
            aoc_pack = oead.Sarc(aoc_field.read_bytes())
            for file in aoc_pack.get_files():
                ex_out = (tmp_dir / util.get_dlc_path() /
                          ("0010" if util.get_settings("wiiu") else "") /
                          file.name)
                ex_out.parent.mkdir(parents=True, exist_ok=True)
                ex_out.write_bytes(file.data)
        aoc_field.write_bytes(b"")

    this_pool = pool or Pool(maxtasksperchild=500)
    results = this_pool.map(
        partial(_check_modded, tmp_dir=tmp_dir),
        {
            f
            for f in tmp_dir.rglob("**/*")
            if f.is_file() and "options" not in f.relative_to(tmp_dir).parts
        },
    )
    for result in results:
        if result:
            modded_files.append(result)
    total = len(modded_files)
    print(f'Found {total} modified file{"s" if total > 1 else ""}')

    total = 0
    sarc_files = {f for f in modded_files if f.suffix in util.SARC_EXTS}
    if sarc_files:
        print("Scanning files packed in SARCs...")
        for files in this_pool.imap_unordered(
                partial(find_modded_sarc_files, tmp_dir=tmp_dir), sarc_files):
            total += len(files)
            modded_files.extend(files)
        print(f'Found {total} modified packed file{"s" if total > 1 else ""}')
    if not pool:
        this_pool.close()
        this_pool.join()
    return modded_files
示例#2
0
def find_modded_files(
    tmp_dir: Path,
    pool: Optional[multiprocessing.pool.Pool] = None
) -> List[Union[Path, str]]:
    modded_files = []
    if isinstance(tmp_dir, str):
        tmp_dir = Path(tmp_dir)

    if (tmp_dir / util.get_dlc_path()).exists():
        try:
            util.get_aoc_dir()
        except FileNotFoundError:
            raise FileNotFoundError(
                "This mod uses DLC files, but BCML cannot locate the DLC folder in "
                "your game dump.")

    aoc_field = (tmp_dir / util.get_dlc_path() /
                 ("0010" if util.get_settings("wiiu") else "") / "Pack" /
                 "AocMainField.pack")
    if aoc_field.exists() and aoc_field.stat().st_size > 0:
        if not list((tmp_dir / util.get_dlc_path() /
                     ("0010" if util.get_settings("wiiu") else "")
                     ).rglob("Map/**/?-?_*.smubin")):
            aoc_pack = oead.Sarc(aoc_field.read_bytes())
            for file in aoc_pack.get_files():
                ex_out = (tmp_dir / util.get_dlc_path() /
                          ("0010" if util.get_settings("wiiu") else "") /
                          file.name)
                ex_out.parent.mkdir(parents=True, exist_ok=True)
                ex_out.write_bytes(file.data)
        aoc_field.write_bytes(b"")

    modded_files = [
        f if "//" in f else Path(f) for f in rsext.find_modified_files(
            str(tmp_dir), util.get_settings("wiiu"))
    ]
    return modded_files
示例#3
0
文件: install.py 项目: sammysung/BCML
def find_modded_files(tmp_dir: Path,
                      verbose: bool = False,
                      original_pool: Pool = None) -> List[Union[Path, str]]:
    """
    Detects all of the modified files in an extracted mod

    :param tmp_dir: The path to the base directory of the mod.
    :type tmp_dir: class:`pathlib.Path`
    :param deep_merge: Whether to log diffs for individual AAMP and BYML files, defaults to False
    :type deep_merge: bool, optional
    :param verbose: Specifies whether to return more detailed output
    :type verbose: bool, optional
    :returns: Returns a tuple with a dict of modified files and the RSTB entries, a list of changes,
    and (if deep merge) diffs of modded BYML and AAMP files
    :rtype: (dict of class:`pathlib.Path`: int, list of str, dict of str: str)
    """
    modded_files = []
    if isinstance(tmp_dir, str):
        tmp_dir = Path(tmp_dir)
    rstb_path = tmp_dir / 'content' / 'System' / 'Resource' /\
                'ResourceSizeTable.product.srsizetable'
    if rstb_path.exists():
        rstb_path.unlink()

    if (tmp_dir / 'aoc').exists:
        try:
            util.get_aoc_dir()
        except FileNotFoundError as err:
            err.error_text = (
                'This mod uses DLC files, but you do not appear to have the DLC '
                'installed. If you still want to use this mod, unpack it and '
                'remove the "aoc" folder.')
            raise err

    aoc_field = tmp_dir / 'aoc' / '0010' / 'Pack' / 'AocMainField.pack'
    if aoc_field.exists() and aoc_field.stat().st_size > 0:
        with aoc_field.open('rb') as a_file:
            sarc.read_file_and_make_sarc(a_file).extract_to_dir(
                str(tmp_dir / 'aoc' / '0010'))
        aoc_field.write_bytes(b'')

    for file in tmp_dir.rglob('**/*'):
        if file.is_file():
            canon = util.get_canon_name(file.relative_to(tmp_dir).as_posix())
            if canon is None:
                if verbose:
                    print(
                        f'Ignored unknown file {file.relative_to(tmp_dir).as_posix()}'
                    )
                continue
            if util.is_file_modded(canon, file, True):
                modded_files.append(file)
                if verbose:
                    print(f'Found modded file {canon}')
            else:
                if 'Aoc/0010/Map/MainField' in canon:
                    file.unlink()
                if verbose:
                    print(f'Ignored unmodded file {canon}')
                continue
    total = len(modded_files)
    print(f'Found {total} modified file{"s" if total > 1 else ""}')

    total = 0
    sarc_files = [
        file for file in modded_files if file.suffix in util.SARC_EXTS
    ]
    if sarc_files:
        print(f'Scanning files packed in SARCs...')
        num_threads = min(len(sarc_files), cpu_count() - 1)
        pool = original_pool or Pool(processes=num_threads)
        modded_sarc_files = pool.map(
            partial(find_modded_sarc_files, tmp_dir=tmp_dir, verbose=verbose),
            sarc_files)
        for files in modded_sarc_files:
            total += len(files)
            modded_files.extend(files)
        if not original_pool:
            pool.close()
            pool.join()
        print(f'Found {total} modified packed file{"s" if total > 1 else ""}')
    return modded_files