コード例 #1
0
def MakeTest(origin, target):
    script_path = util.GetScriptPath()

    util.LogDebug("This is the origin: " + origin)
    util.LogDebug("This is the target: " + target)

    FoldersToCreate = []
    FilesToCreate = []
    util.CreateTarget(target)

    util.LogDebug("Target Created")

    for root, subdirs, files in os.walk(origin):
        if root != origin:
            FoldersToCreate.append(root)
            util.LogDebug("Adding folder ({})".format(root))
        for filename in files:
            file_path = os.path.join(root, filename)
            FilesToCreate.append(file_path)
            util.LogDebug("Adding file ({})".format(file_path))
    for folderToCreate in FoldersToCreate:
        util.LogDebug("About to add folder ({})".format(folderToCreate))
        newFolderName = folderToCreate.replace(origin, target)
        util.LogDebug("New folder name is ({})".format(newFolderName))
        os.mkdir(newFolderName)

    for fileToCreate in FilesToCreate:
        util.LogDebug("About to add file ({})".format(fileToCreate))
        newFileName = fileToCreate.replace(origin, target)
        util.LogDebug("New filename is ({})".format(newFileName))
        with open(newFileName, "w") as myFile:
            myFile.write("TESTFILE")
コード例 #2
0
def ReconcileHKX(mod_path, oldrim_path):

    script_path = util.GetScriptPath()

    util.LogInfo("Reconcile HKX")
    util.LogDebug("This is the mod_path: " + mod_path)
    util.LogDebug("This is the oldrim_path " + oldrim_path)

    CopyHKX = []
    totalCount = 0
    matchedCount = 0
    for root, subdirs, files in os.walk(mod_path):
        util.LogDebug("Walking folder " + root)
        for filename in files:
            if filename.lower().endswith(".hkx"):
                file_path = os.path.join(root, filename)
                relative_path = os.path.relpath(file_path, mod_path)

                util.LogDebug("Relative path {} OR Path {}".format(
                    relative_path, oldrim_path))
                oldrim_file_path = os.path.join(oldrim_path, relative_path)
                totalCount += 1
                util.LogDebug("Found {}, checking {}".format(
                    file_path, oldrim_file_path))
                if os.path.exists(oldrim_file_path):
                    util.LogDebug(
                        "Found {} match in oldrim".format(oldrim_file_path))
                    matchedCount += 1
                    CopyHKX.append((file_path, oldrim_file_path))
    util.LogInfo("Matched {}/{} hkx files in the mod".format(
        matchedCount, totalCount))

    for i in range(len(CopyHKX)):
        (copy_to, copy_from) = CopyHKX[i]
        util.LogDebug("Copying {}->{}".format(copy_from, copy_to))
        shutil.copy2(copy_from, copy_to)
        sys.stdout.write("Reconciled {}/{} \r".format(i + 1, len(CopyHKX)))
        sys.stdout.flush()
    sys.stdout.write("\n")
コード例 #3
0
def ConvertPath(mod_name, target):

    script_path = util.GetScriptPath()

    util.LogInfo("Convert Path")
    util.LogDebug("This is the target: " + target)
    util.LogDebug("This is the mod name " + mod_name)

    has_havoc = util.HasHavokBPP()

    do_meshes = \
     toolkit_config.get_bool_setting("Meshes", "RemoveEditorMarker") or \
     toolkit_config.get_bool_setting("Meshes", "PrettySortBlocks") or \
     toolkit_config.get_bool_setting("Meshes", "TrimTexturesPath") or \
     toolkit_config.get_bool_setting("Meshes", "OptimizeForSSE")

    NoConversion = {}
    WarnConversion = {}
    ConvertListDDS = []
    ConvertListHKX = []
    ConvertListHKX64 = []
    ConvertListTXT = []
    ConvertListSound = []
    ConvertListMesh = []
    for root, subdirs, files in os.walk(target):
        if root != target:
            util.LogDebug("Walking folder " + root)
            for filename in files:
                #util.LogDebug("filename: {}".format(filename))
                if filename.lower().endswith(".dds"):
                    file_path = os.path.join(root, filename)
                    ddsChecked = check_dds.CheckDDS(file_path, file_path)
                    if ddsChecked == check_dds.PC:
                        ConvertListDDS.append(file_path)
                    elif ddsChecked == check_dds.NX:
                        if 'DDS' not in NoConversion:
                            NoConversion['DDS'] = 0
                        NoConversion['DDS'] += 1
                    else:
                        if 'DDS' not in WarnConversion:
                            WarnConversion['DDS'] = []
                        WarnConversion['DDS'].append(
                            (filename, "Unknown DDS format"))
                elif filename.lower().endswith(".hkx"):
                    file_path = os.path.join(root, filename)
                    hkxChecked = check_hkx.CheckHKX(file_path, file_path)
                    if hkxChecked == check_hkx.PC_32:
                        ConvertListHKX.append(file_path)
                    elif hkxChecked == check_hkx.PC_XML:
                        ConvertListHKX.append(file_path)
                    elif hkxChecked == check_hkx.PC_64:
                        # if root.lower().find("behaviors") > 0 or filename.lower().find("skeleton") > 0:
                        # 	if 'HKX' not in WarnConversion:
                        # 		WarnConversion['HKX'] = []
                        # 	WarnConversion['HKX'].append( (filename, "SSE hkx animation") )
                        # else:
                        ConvertListHKX64.append(file_path)
                    elif hkxChecked == check_hkx.NX_64:
                        if 'HKX' not in NoConversion:
                            NoConversion['HKX'] = 0
                        NoConversion['HKX'] += 1
                    else:
                        if 'HKX' not in WarnConversion:
                            WarnConversion['HKX'] = []
                        WarnConversion['HKX'].append(
                            (filename, "Unknown hkx animation format"))

                elif filename.lower().startswith(
                        "translate_") and filename.lower().endswith(".txt"):
                    file_path = os.path.join(root, filename)
                    ConvertListTXT.append(file_path)
                elif filename.lower().endswith(".xwm") or filename.lower(
                ).endswith(".fuz") or filename.lower().endswith(".wav"):
                    file_path = os.path.join(root, filename[:-4])
                    if not file_path in ConvertListSound:
                        ConvertListSound.append(file_path)
                elif filename.lower().endswith(".nif"):
                    file_path = os.path.join(root, filename)
                    ConvertListMesh.append(file_path)

    for fileType in NoConversion:
        util.LogInfo("Found {} {} files that are already in NX format".format(
            NoConversion[fileType], fileType))
    for fileType in WarnConversion:
        fileTypeWarnings = WarnConversion[fileType]
        for i in range(len(fileTypeWarnings)):
            util.LogInfo("Warning, cannot convert {} because <{}>".format(
                fileTypeWarnings[i][0], fileTypeWarnings[i][1]))

    util.LogInfo("Found {} dds files to convert".format(len(ConvertListDDS)))
    if has_havoc:
        util.LogInfo("Found {} 32-bit hkx files to convert".format(
            len(ConvertListHKX)))
    else:
        util.LogInfo(
            "Found {} 32-bit hkx files that won't convert as Havoc utility wasn't found."
            .format(len(ConvertListHKX)))
    util.LogInfo("Found {} 64-bit hkx files to convert".format(
        len(ConvertListHKX64)))
    util.LogInfo("Found {} txt files to convert".format(len(ConvertListTXT)))
    util.LogInfo("Found {} sound files to convert".format(
        len(ConvertListSound)))
    if do_meshes:
        util.LogInfo("Found {} mesh files to convert".format(
            len(ConvertListMesh)))
    else:
        util.LogInfo("Found {} mesh files but won't touch them.".format(
            len(ConvertListMesh)))
    '''
	def LogProgress(convertList, convertFn, name):
		if len(convertList) > 0:
			failedCount = 0
			for i in range(len(convertList)):
				file_path = convertList[i]
				success = convertFn(target, file_path)
				if not success:
					failedCount += 1
				sys.stdout.write("Converted {}/{} {} ({}) failed. \r".format(i+1, len(convertList), name, failedCount))
				sys.stdout.flush()
			sys.stdout.write("\n")
	'''
    def LogProgress(convertList, fnName, convertFn, name, threadSetting):
        if len(convertList) > 0:
            failedCount = 0
            maxThreads = toolkit_config.get_int_setting(
                "Performance", threadSetting)

            jm = job_manager.JobManager(maxThreads)
            convertedCount = 0
            processedCount = 0
            totalCount = len(convertList)

            def cb(success):
                nonlocal processedCount, convertedCount, failedCount
                processedCount += 1
                if success:
                    convertedCount += 1
                else:
                    failedCount += 1
                sys.stdout.write(
                    "{} Processed {}/{} ({}/{}) success/failure. \r".format(
                        name, processedCount, totalCount, convertedCount,
                        failedCount))
                sys.stdout.flush()

            for i in range(len(convertList)):
                file_path = convertList[i]
                job = job_manager.Job(cb, fnName, convertFn, target.lower(),
                                      file_path.lower())
                jm.AddJob(job)

            jm.ProcessBatch()
            sys.stdout.write(
                "{} Processing Complete: {}/{} ({}/{}) success/failure. \r".
                format(name, processedCount, totalCount, convertedCount,
                       failedCount))
            sys.stdout.write("\n")
            if processedCount != totalCount:
                sys.stdout.write("Not all were processed.\n")
            sys.stdout.flush()

    LogProgress(ConvertListDDS, "ConvertDDS", convert_dds.ConvertDDS, "DDS",
                "MaxTextureThreads")
    if has_havoc:
        LogProgress(ConvertListHKX, "ConvertHKX", convert_hkx.ConvertHKX,
                    "HKX 32-bit", "MaxAnimationThreads")
    LogProgress(ConvertListHKX64, "ConvertHKX64", convert_hkx64.ConvertHKX64,
                "HKX 64-bit", "MaxAnimationThreads")
    LogProgress(ConvertListTXT, "ConvertTXT", convert_txt.ConvertTXT, "TXT",
                "MaxOtherThreads")
    LogProgress(ConvertListSound, "ConvertSound", convert_sound.ConvertSound,
                "Sounds", "MaxSoundThreads")
    if do_meshes:
        LogProgress(ConvertListMesh, "ConvertMesh", convert_nif.ConvertNIF,
                    "Meshes", "MaxMeshThreads")
コード例 #4
0
def PackMod(mod_name, target):
    script_path = util.GetScriptPath()
    utilities_path = util.GetUtilitiesPath()
    bsarch = os.path.join(utilities_path, "bsarch.exe")
    util.LogDebug("This is the target: " + target)
    util.LogDebug("This is the mod name " + mod_name)
    util.LogInfo("Pack Mod")

    has_archive = util.HasArchive()
    util.LogDebug("HasArchive is {}".format(has_archive))

    data_list = os.listdir(target)
    util.LogDebug(str(data_list))

    BSARules = bsa_rules.GetBSARules()

    BSAs = {}

    SafePlugins = [
        "skyrim.esm", "dawnguard.esm", "hearthfires.esm", "dragonborn.esm"
    ]
    PluginPaths = {}
    for plugin in SafePlugins:
        PluginPaths[plugin] = plugin

    # Arbitrary Limit to search for merged plugin list
    LineLimit = 10
    ChunkSize = 1024
    ChunksLimit = 10
    childPattern = re.compile(r"Merged Plugin:([^\0]*)[\0]", re.MULTILINE)
    espPattern = re.compile(r"(.+?\.[^.]*$|$)", re.MULTILINE)

    def ReadPlugin(filename):
        util.LogDebug("Reading plugin{}".format(filename))
        pluginList = []
        with open(filename, "rb") as plugin:
            lineNumber = 0
            chunkNumber = 0
            foundMerge = False
            buffer = ''
            while True:
                chunk = plugin.read(ChunkSize)
                chunkNumber += 1
                buffer = buffer + "".join(map(chr, chunk))
                if "Merged Plugin:" in buffer:
                    foundMerge = True
                if foundMerge:
                    childPlugins = re.search(childPattern, buffer)
                    if childPlugins != None:
                        wholePattern = childPlugins.group(0)
                        value = childPlugins.group(1)
                        util.LogDebug("Found Plugins Block <{}>".format(value))
                        while True:
                            espTest = re.findall(espPattern, value)
                            if espTest != None:
                                for espCandidate in espTest:
                                    espCandidate = espCandidate.strip(
                                    )  #''.join(espCandidate.split())
                                    if espCandidate != '':
                                        util.LogDebug(
                                            "Found <{}>".format(espCandidate))
                                        pluginList.append(espCandidate.lower())
                                #util.LogInfo("Found <{}>".format(str(espTest)))
                                break
                        break
                    if chunkNumber >= ChunksLimit:
                        break
                if not foundMerge:
                    lineNumber += 1
                    if lineNumber >= LineLimit:
                        break
        return pluginList

    mod_pathname = mod_name + ".esp"
    for root, subdirs, files in os.walk(target):
        for file in files:
            if file.endswith(".esp") or file.endswith(".esm"):
                filename = os.path.join(root, file)
                util.LogDebug("Found a plugin at {}, <{}>".format(
                    filename, file))

                # look after yourself
                PluginPaths[file.lower()] = file.lower()

                childrenOfPlugin = ReadPlugin(filename)
                if len(childrenOfPlugin) > 0:
                    util.LogInfo(
                        "Detected that {} is merged from:".format(file))
                    for child in childrenOfPlugin:
                        util.LogInfo(" - {}".format(child))
                        # look after your children
                        PluginPaths[child.lower()] = file.lower()
                mod_pathname = file
        # only interested in files in the root folder
        break

    util.LogDebug("PluginPaths is <{}>".format(str(PluginPaths)))

    def DefineBSA(bsa_name):
        nonlocal BSAs
        temp = os.path.join(target, "Temp")
        if bsa_name != '':
            temp = os.path.join(target, "Temp - " + bsa_name)

        temp_data = os.path.join(temp, "Data")
        util.RemoveTree(temp)
        os.makedirs(temp_data, exist_ok=True)
        BSAs[bsa_name] = temp_data

    numFoldersToMove = 0
    numFilesToMove = 0
    numFoldersMoved = 0
    numFilesMoved = 0

    def ApplyRuleToFolder(rule, folder):
        nonlocal numFoldersMoved
        bsa_name = rule["BSA"]
        if bsa_name not in BSAs:
            DefineBSA(bsa_name)

        move_to_folder = BSAs[bsa_name]
        child = os.path.basename(folder)
        parent = os.path.dirname(folder)
        if parent != target:
            util.LogDebug("parent is not target")
            rel_parent = os.path.relpath(parent, target)
            util.LogDebug("rel_parent is {}".format(rel_parent))
            move_to_folder = os.path.join(move_to_folder, rel_parent, child)
            util.LogDebug("move_to_folder is {}".format(move_to_folder))
        shutil.move(folder, move_to_folder)
        util.LogDebug("moving {} to {}".format(folder, move_to_folder))
        numFoldersMoved += 1
        sys.stdout.write("Moved Files {}/{} Folders {}/{} \r".format(
            numFilesMoved, numFilesToMove, numFoldersMoved, numFoldersToMove))
        sys.stdout.flush()

    def ApplyRuleToFile(rule, file_path):
        nonlocal numFilesMoved
        bsa_name = rule["BSA"]
        if bsa_name not in BSAs:
            DefineBSA(bsa_name)
        relative_path = os.path.relpath(file_path, target)
        target_path = os.path.join(BSAs[bsa_name], relative_path)
        target_folder = os.path.dirname(target_path)

        os.makedirs(target_folder, exist_ok=True)
        util.LogDebug("moving {} to {}".format(file_path, target_path))
        shutil.move(file_path, target_path)
        numFilesMoved += 1
        sys.stdout.write("Moved Files {}/{} Folders {}/{} \r".format(
            numFilesMoved, numFilesToMove, numFoldersMoved, numFoldersToMove))
        sys.stdout.flush()

    ignoreMovedFolders = []
    for root, subdirs, files in os.walk(target):
        relative_folder = os.path.relpath(root, target).lower()
        if root != target:
            # Check if this folder is ignored already
            ignoreThisFolder = False
            for ignored in ignoreMovedFolders:
                if relative_folder.startswith(ignored):
                    ignoreThisFolder = True
            if not ignoreThisFolder:
                # Now check if there is an unqualified path rule for this folder (like "scripts" are only placed in Misc)
                folderCount = 0
                lastRuleMatch = None
                for rule in BSARules:
                    if "Folder" in rule and relative_folder.startswith(
                            rule["Folder"]):
                        folderCount += 1
                        lastRuleMatch = rule
                if folderCount == 1:
                    numFoldersToMove += 1
                    ignoreMovedFolders.append(relative_folder)
                else:
                    for filename in files:
                        util.LogDebug(os.path.join(relative_folder, filename))
                        numFilesToMove += 1
    util.LogInfo("Files ({}) / Folders ({}) to move".format(
        numFilesToMove, numFoldersToMove))

    RemoveFolders = []
    for root, subdirs, files in os.walk(target):
        relative_folder = os.path.relpath(root, target).lower()
        #util.LogDebug("Walking relative folder " + relative_folder)
        if root == target:
            for child in subdirs:
                util.LogDebug("Children {}".format(child))
                RemoveFolders.append(os.path.join(target, child))
        else:
            # First check if there is an unqualified path rule for this folder (like "scripts" are only placed in Misc)
            folderCount = 0
            lastRuleMatch = None
            for rule in BSARules:
                if "Folder" in rule and relative_folder.startswith(
                        rule["Folder"]):
                    folderCount += 1
                    lastRuleMatch = rule
            if folderCount == 1:
                util.LogDebug("ApplyRuleToFolder({}) -> {}".format(
                    lastRuleMatch["BSA"], relative_folder))
                ApplyRuleToFolder(lastRuleMatch, root)
            else:
                #util.LogDebug("No folder match, check files")
                for filename in files:
                    filename = filename.lower()
                    file_path = os.path.join(root, filename)
                    relative_path = os.path.relpath(file_path, target)
                    should_apply = False
                    for rule in BSARules:
                        should_apply = True
                        if should_apply and "Folder" in rule:
                            #util.LogDebug("checking folder rule {} vs relative_folder {}".format(rule["Folder"], relative_folder))
                            should_apply = should_apply and relative_folder.startswith(
                                rule["Folder"])
                        if should_apply and "Extension" in rule:
                            #util.LogDebug("checking extension rule {} vs filename {}".format(rule["Extension"], filename))
                            should_apply = should_apply and filename.endswith(
                                rule["Extension"])
                        if should_apply:
                            util.LogDebug("Applying BSA {} for {}".format(
                                rule["BSA"], file_path))
                            ApplyRuleToFile(rule, file_path)
                            break
                    if not should_apply:
                        util.LogWarn("Could not apply rule for <{}>".format(
                            relative_path))
                        for rule in BSARules:
                            should_apply = True
                            if should_apply and "Folder" in rule:
                                util.LogDebug(
                                    "checking folder rule {} vs relative_folder {}"
                                    .format(rule["Folder"], relative_folder))
                                should_apply = should_apply and relative_folder.startswith(
                                    rule["Folder"])
                            if should_apply and "Extension" in rule:
                                util.LogDebug(
                                    "checking extension rule {} vs filename {}"
                                    .format(rule["Extension"], filename))
                                should_apply = should_apply and filename.endswith(
                                    rule["Extension"])
    sys.stdout.write("\n")
    util.LogInfo("Cleanup old folders")
    for folder in RemoveFolders:
        util.LogDebug("Cleanup {}".format(folder))
        util.RemoveTree(folder)

    def CleanPluginSpecificPaths(cleanup_directory):
        MoveFromTo = []
        DeleteUnmatched = []
        for root, subdirs, files in os.walk(cleanup_directory):
            directory = root.lower()
            dir_name = os.path.basename(directory)
            if (dir_name.endswith("esm") or
                    dir_name.endswith("esp")) and dir_name not in SafePlugins:
                if dir_name in PluginPaths:
                    target_pathname = PluginPaths[dir_name.lower()]
                    new_path = os.path.join(os.path.dirname(directory),
                                            target_pathname)
                    if not os.path.isdir(new_path):
                        util.LogDebug(
                            "Rename plugin directory {} to {}".format(
                                directory, new_path))
                        os.rename(directory, new_path)
                    else:
                        util.LogDebug(
                            "Move plugin files from directory {} to {}".format(
                                directory, new_path))
                        MoveFromTo.append((directory, new_path))
                else:
                    util.LogWarn("Marking <{}> for deletion.".format(dir_name))
                    DeleteUnmatched.append(directory)

        for moveFromTo in MoveFromTo:
            (move_from, move_to) = moveFromTo
            util.LogDebug("Need to move from {} to {}".format(
                move_from, move_to))
            for root, subdirs, files in os.walk(move_from):
                for file in files:
                    file_path = os.path.join(root, file)
                    relative_path = os.path.relpath(root, move_from)
                    new_path = os.path.join(move_to, relative_path, file)

                    util.LogDebug("Moving file from {} to {}".format(
                        file_path, new_path))
                    new_directory = os.path.dirname(new_path)
                    os.makedirs(new_directory, exist_ok=True)
                    shutil.move(file_path, new_path)
        for deleteDirectory in DeleteUnmatched:
            util.LogDebug("Deleting <{}>".format(deleteDirectory))
            util.RemoveTree(deleteDirectory)
            util.LogDebug("Deleted <{}>".format(deleteDirectory))

    util.LogDebug("Build BSAs")
    bsaList = []
    for bsa_name in BSAs:
        temp_data = BSAs[bsa_name]
        temp = os.path.dirname(temp_data)
        bsa_file_suffix = ""
        if bsa_name != "":
            bsa_file_suffix = " - " + bsa_name

        CleanPluginSpecificPaths(temp_data)
        bsa_filename = mod_name + bsa_file_suffix + ".bsa"
        target_bsa = os.path.join(target, bsa_filename)
        useArchive = has_archive
        if useArchive:
            bsa_list = archive_bsa.ArchiveBSA(temp, bsa_filename)
            for bsa_info in bsa_list:
                bsa_filename = bsa_info["FileName"]
                bsa_filepath = bsa_info["Folder"]
                bsa_fullpath = os.path.join(bsa_filepath, bsa_filename)
                newTargetBSA = os.path.join(target, bsa_filename)
                shutil.move(bsa_fullpath, newTargetBSA)
                bsaList.append(newTargetBSA)
        else:
            bsa_list = bsarch_bsa.BsarchBSA(temp, target_bsa)
            for bsa_info in bsa_list:
                bsa_filename = bsa_info["FileName"]
                bsa_filepath = bsa_info["Folder"]
                bsa_fullpath = os.path.join(bsa_filepath, bsa_filename)
                newTargetBSA = os.path.join(target, bsa_filename)
                shutil.move(bsa_fullpath, newTargetBSA)
                bsaList.append(newTargetBSA)
        util.RemoveTree(temp)

    util.LogDebug("PackMod Done")
    return bsaList
コード例 #5
0
def BsarchBSA(target_folder, bsa_filename):
    script_path = util.GetScriptPath()
    utilities_path = util.GetUtilitiesPath()
    bsarch = os.path.join(utilities_path, "bsarch.exe")

    log_basename = "log.txt"
    log_filename = os.path.join(target_folder, log_basename)
    config_basename = "bsa_config.txt"
    config_filename = os.path.join(target_folder, config_basename)
    allFilesList = []

    Flag_NamedDir = 1
    Flag_NamedFiles = 2
    Flag_Compressed = 4
    Flag_RetainDir = 8
    Flag_RetainName = 16
    Flag_RetainFOff = 32
    Flag_XBox360 = 64
    Flag_StartupStr = 128
    Flag_EmbedName = 256
    Flag_XMem = 512
    Flag_Bit = 1024

    flags = bitflag.BitFlag()

    flags.SetFlag(Flag_NamedDir)
    flags.SetFlag(Flag_NamedFiles)

    util.LogInfo("Build File List")
    totalFileSizeTally = 0
    target_data = os.path.join(target_folder, "Data")
    util.LogDebug("Walking the target directory " + target_data)
    bsaFolders = []

    SizeLimitBSA = bsa_rules.BSASizeLimit

    totalFileCount = 0
    for root, subdirs, files in os.walk(target_data):
        util.LogDebug('--\nroot = ' + root)
        if root != target_data:
            for filename in files:
                if filename != "desktop.ini" and filename != 'thumbs.db':
                    file_path = os.path.join(root, filename)

                    file_size = os.path.getsize(file_path)
                    totalFileSizeTally += file_size
                    totalFileCount += 1

    currentFileIndex = None
    if totalFileSizeTally > SizeLimitBSA:
        currentFileIndex = 0

    totalWrittenTally = 0

    currentFileSizeTally = 0
    buffer = ''
    bsaFileWritten = []
    bsa_original_filename = bsa_filename
    temp_data = os.path.join(os.path.dirname(target_data), "Ready")

    def WriteBSA():
        nonlocal currentFileIndex, bsa_filename
        util.LogDebug("Writing BSA")

        if currentFileIndex != None:
            bsa_filename = bsa_original_filename[:-4] + str(
                currentFileIndex) + ".bsa"
            currentFileIndex += 1

        util.LogInfo("Run bsarch.exe")

        flags_value = flags.GetValue()
        flags_hexvalue = hex(flags_value)
        compress = "-z" if flags.IsSet(Flag_Compressed) else ""

        commandLine = [
            bsarch, "pack", temp_data, bsa_filename, "-sse", compress,
            "-af:" + flags_hexvalue
        ]
        util.RunCommandLine(commandLine)

        bsaFileWritten.append({
            "Folder": target_folder,
            "FileName": bsa_filename
        })
        util.RemoveTree(temp_data)

    filesArchived = 0
    for root, subdirs, files in os.walk(target_data):
        util.LogDebug('--\nroot = ' + root)
        if root == target_data:
            util.LogDebug("subdirs: " + str(subdirs))
            lower_case_data_list = [x.lower() for x in subdirs]
            util.LogDebug("lcds: " + str(lower_case_data_list))
            if "meshes" in lower_case_data_list:
                util.LogDebug("found meshes")
                flags.SetFlag(Flag_StartupStr)
                flags.SetFlag(Flag_Compressed)
            if "textures" in lower_case_data_list:
                util.LogDebug("found textures")
            if "interface" in lower_case_data_list:
                util.LogDebug("found interface")
            if "music" in lower_case_data_list:
                util.LogDebug("found music")
                flags.SetFlag(Flag_RetainName)
            if "sound" in lower_case_data_list:
                util.LogDebug("found sound")
                sound_list = os.listdir(os.path.join(target_data, "sound"))
                sound_list_lower = [x.lower() for x in sound_list]

                if "fx" in sound_list_lower:
                    util.LogDebug("found sound//fx")
                    flags.SetFlag(Flag_RetainName)
                if "voice" in sound_list_lower:
                    util.LogDebug("found sound//voice")
            if "shadersfx" in lower_case_data_list:
                util.LogDebug("found shaders")
            if "seq" in lower_case_data_list:
                util.LogDebug("found seq")
                flags.SetFlag(Flag_RetainName)
            if "grass" in lower_case_data_list:
                util.LogDebug("found grass")
                flags.SetFlag(Flag_RetainName)
            if "scripts" in lower_case_data_list:
                util.LogDebug("found scripts")
                flags.SetFlag(Flag_RetainName)
        else:
            for filename in files:
                if filename != "desktop.ini" and filename != 'thumbs.db':
                    file_path = os.path.join(root, filename)

                    file_size = os.path.getsize(file_path)
                    newTally = currentFileSizeTally + file_size
                    util.LogDebug("Attempting to add " + file_path +
                                  " currentFileSizeTally is " +
                                  str(currentFileSizeTally) +
                                  " file_size is " + str(file_size))
                    if (newTally >= SizeLimitBSA):
                        util.LogDebug(
                            "New BSA would be too big, writing current BSA")
                        sys.stdout.write("\n")
                        WriteBSA()

                        currentFileSizeTally = 0

                    relative_path = file_path.replace(target_folder, '')

                    path_no_data = relative_path[6:]
                    temp_path = os.path.join(temp_data, path_no_data)
                    util.LogDebug("Moving <{}> to <{}>".format(
                        file_path, temp_path))
                    paths_to_create = []
                    check_path = os.path.dirname(temp_path)

                    util.LogDebug("Checking path {}".format(check_path))
                    while not os.path.isdir(check_path):
                        util.LogDebug("{} does not exist.".format(check_path))
                        paths_to_create.insert(0, check_path)
                        check_path = os.path.dirname(check_path)
                        util.LogDebug("Checking path {}".format(check_path))
                    for path_to_create in paths_to_create:
                        util.LogDebug("{} does not exist.".format(check_path))
                        os.mkdir(path_to_create)
                    shutil.move(file_path, temp_path)
                    currentFileSizeTally += file_size
                    filesArchived += 1
                    sys.stdout.write("Prepared {}/{} \r".format(
                        filesArchived, totalFileCount))
                    sys.stdout.flush()
    sys.stdout.write("\n")
    if currentFileSizeTally > 0:
        WriteBSA()

    util.LogInfo("Clean Up")

    os.chdir(script_path)
    return bsaFileWritten
コード例 #6
0
def ArchiveBSA(target_folder, bsa_filename):
    script_path = util.GetScriptPath()
    utilities_path = util.GetUtilitiesPath()
    archive_original = os.path.join(utilities_path, "Archive.exe")

    util.LogDebug("Copy Archive.exe to target folder")
    archive = os.path.join(target_folder, "Archive.exe")
    shutil.copy2(archive_original, archive)

    log_basename = "log.txt"
    log_filename = os.path.join(target_folder, log_basename)
    config_basename = "bsa_config.txt"
    config_filename = os.path.join(target_folder, config_basename)
    allFilesList = []

    checks = {}
    util.LogInfo("Build File List")
    totalFileSizeTally = 0
    target_data = os.path.join(target_folder, "Data")
    util.LogDebug("Walking the target directory " + target_data)
    for root, subdirs, files in os.walk(target_data):
        util.LogDebug('--\nroot = ' + root)
        if root == target_data:
            util.LogDebug("subdirs: " + str(subdirs))
            lower_case_data_list = [x.lower() for x in subdirs]
            util.LogDebug("lcds: " + str(lower_case_data_list))
            if "meshes" in lower_case_data_list:
                util.LogDebug("found meshes")
                checks["Retain Strings During Startup"] = True
                checks["Meshes"] = True
            if "textures" in lower_case_data_list:
                util.LogDebug("found texttures")
                checks["Textures"] = True
            if "interface" in lower_case_data_list:
                util.LogDebug("found interface")
                checks["Menus"] = True
            if "music" in lower_case_data_list:
                util.LogDebug("found music")
                checks["Retain File Names"] = True
                checks["Sounds"] = True
            if "sound" in lower_case_data_list:
                util.LogDebug("found sound")
                sound_list = os.listdir(os.path.join(target_data, "sound"))
                sound_list_lower = [x.lower() for x in sound_list]

                if "fx" in sound_list_lower:
                    util.LogDebug("found sound//fx")
                    checks["Retain File Names"] = True
                    checks["Sounds"] = True
                if "voice" in sound_list_lower:
                    util.LogDebug("found sound//voice")
                    checks["Voices"] = True
            if "shadersfx" in lower_case_data_list:
                util.LogDebug("found shaders")
                checks["Shaders"] = True
            if "seq" in lower_case_data_list:
                util.LogDebug("found seq")
                checks["Retain File Names"] = True
                checks["Misc"] = True
            if "grass" in lower_case_data_list:
                util.LogDebug("found grass")
                checks["Retain File Names"] = True
                checks["Misc"] = True
            if "scripts" in lower_case_data_list:
                util.LogDebug("found scripts")
                checks["Retain File Names"] = True
                checks["Misc"] = True
        else:
            for filename in files:
                if filename != "desktop.ini":
                    file_path = os.path.join(root, filename)
                    relative_path = file_path.replace(target_folder, '')

                    util.LogDebug('\t- file %s (relative path: %s)' %
                                  (filename, relative_path))
                    path_no_data = relative_path[6:]
                    file_size = os.path.getsize(file_path)
                    totalFileSizeTally += file_size
                    util.LogDebug("totalFileSizeTally is now: " +
                                  str(totalFileSizeTally))
                    allFilesList.append({
                        'FileName': filename,
                        'FilePath': file_path,
                        'RelativePath': relative_path,
                        'PathNoData': path_no_data,
                        'FileSize': file_size
                    })

    SizeLimitBSA = bsa_rules.BSASizeLimit

    currentFileIndex = None
    currentFileSizeTally = 0
    buffer = ''
    bsaFileWritten = []
    bsa_original_filename = bsa_filename

    def WrtiteBSA():
        nonlocal currentFileIndex, buffer, bsa_filename
        util.LogDebug("Writing BSA with filelist:<" + buffer + ">")
        filelist_basename = "bsa_filelist.txt"
        if currentFileIndex != None:
            filelist_basename = "bsa_filelist" + str(currentFileIndex) + ".txt"
            bsa_filename = bsa_original_filename[:-4] + str(
                currentFileIndex) + ".bsa"
            currentFileIndex += 1

        filelist_filename = os.path.join(target_folder, filelist_basename)
        with open(filelist_filename, 'w') as filelist_file:
            filelist_file.write(buffer)
        buffer = ''
        util.LogInfo("Build Config")
        checksOrder = [
            "Meshes", "Textures", "Menus", "Sounds", "Voices", "Shaders",
            "Trees", "Fonts", "Misc", "Compress Archive",
            "Retain Directory Names", "Retain File Names",
            "Retain File Name Offsets", "Retain Strings During Startup",
            "XBox 360 Archive", "Embed File Names"
        ]
        with open(config_filename, 'w') as config_file:
            config_file.write("Log: " + log_basename + "\n")
            config_file.write("New Archive\n")
            for check in checksOrder:
                if check in checks:
                    config_file.write("Check: " + check + "\n")

            config_file.write("Set File Group Root: Data\\\n")
            config_file.write("Add File Group: " + filelist_basename + "\n")
            config_file.write("Save Archive: " + bsa_filename + "\n")
        util.LogInfo("Run Archive.exe")

        commandLine = ["Archive.exe", config_basename]
        os.chdir(target_folder)
        util.RunCommandLine(commandLine)
        with open(log_filename, "r") as log_file:
            for line in log_file:
                util.LogDebug(line)
        os.remove(log_filename)
        os.remove(filelist_filename)
        os.remove(config_filename)
        bsaFileWritten.append({
            "Folder": target_folder,
            "FileName": bsa_filename
        })

    if totalFileSizeTally > SizeLimitBSA:
        currentFileIndex = 0

    totalWrittenTally = 0
    for fileInfo in allFilesList:
        file_size = fileInfo['FileSize']
        newTally = currentFileSizeTally + file_size
        totalWrittenTally = totalWrittenTally + file_size
        util.LogDebug("Adding " + fileInfo['FileName'] +
                      " currentFileSizeTally is " + str(currentFileSizeTally) +
                      " file_size is " + str(file_size) +
                      " totalWrittenTally is " + str(totalWrittenTally))
        buffer += fileInfo['PathNoData'] + "\n"
        currentFileSizeTally += file_size
        if (newTally >= SizeLimitBSA) or (totalWrittenTally >=
                                          totalFileSizeTally):
            WrtiteBSA()
            currentFileSizeTally = 0

    if buffer != '':
        util.LogWarn("BUFFER NOT EMPTY!")

    util.LogInfo("Clean Up")

    util.RemoveFile(archive)

    os.chdir(script_path)
    return bsaFileWritten