local UnityApplication = CS.UnityEngine.Application local CsApplication = CS.XApplication local CsLog = CS.XLog local CsRemoteConfig = CS.XRemoteConfig local CsTool = CS.XTool local CsGameEventManager = CS.XGameEventManager.Instance local CsInfo = CS.XInfo local CsDownloadService = CS.XDownloadService.Instance local DownloadState = { NONE = -1, DONE = 0, ING = 1, FAIL = 2 } local IosDownloadState = { PreparingLocalFiles = 0, PreparingDownload = 1, Downloading = 2, AppendDownloading = 3, Verifying = 4, Finished = 5 } -- 版更时需要强清本地资源的版本 local ForceVersion = {["1.22.0"] = true} local ForceVersionNum = 22 local SPECIAL_DELETE_MATRIX_PREF_KEY = "__Kuro__reset_Matrix_files_" local LAUNCH_PLAYED_CG = "LAUNCH_PLAYED_CG" local UNCHECKED_FILE_EXTENSION = ".unchecked" local module_creator = function() ---@class XLaunchFileModule 游戏启动文件类 local XLaunchFileModule = {} local MESSAGE_PACK_MODULE_NAME = "XLaunchCommon/XMessagePack" require(MESSAGE_PACK_MODULE_NAME) ---@type XLaunchDlcManager local XLaunchDlcManager = require("XLaunchDlcManager") local SIZE = 10 * 1024 * 1024 local TIMEOUT = 5 * 1000 local READ_TIMEOUT = 10 * 1000 local RETRY = 10 local INDEX = "index" local ResFileType local AppPathModule local AppVersionModule local OnCompleteCallback local OnProgressCallback local OnExitCallback local ApplicationFilePath local DocumentFilePath local DocumentUrl local DocumentIndexDir local DocumentIndexPath local NewVersion local NeedUpdate local HasUpdated -- common local ApplicationIndexTable local DocumentIndexTable local DlcIndexTable local CurrentFileTable = nil local AllFileTableDlc = nil local NeedFileSet = nil local UpdateTable = {} local UpdateTableCount = 0 local UpdateSize = 0 local AllUpdateTable = {} local AllUpdateTableCount = 0 local AllUpdateSize = 0 local DownloadedMap = {} -- local HasLocalFiles = false local IsDebugBuild = CS.XApplication.Debug local IsPause = false local CurrentDownloader local TipsOnce = false -- Local Function local CheckIndexFile local ResolveResIndex local PrepareDownload local DownloadFiles local StopDownloading local CompleteDownload local OnCompleteResFilesInit local LoadIndexTable local LoadIndexTableWithDlcInfo local InitDocumentIndex local DownloadDlcIndexs local DoPrepareDownload local OnNotifyEvent local DoRecord local RemoveEvents local IsFullDownloadSelectType -- DLC分包相关 local DLC_BASE_INDEX = 0 -- 基础包 local DLC_COMMON_INDEX = -1 -- 通用资源 local IsDlcBuild = CsInfo.IsDlcBuild local IsInGame = false local NeedShowSelect = false local DlcNeedFileMap = nil local CheckFixDlcRecord -- 本地测试 local NeedLaunchTest = CS.XResourceManager.NeedLaunchTest -- 调试用,debug环境下测试下载流程 ("Tools/本地下载测试/开启") local LaunchTestPath = UnityApplication.dataPath .. "/../../../Product/Temp/LocalCdn" local LaunchTestDirApp = UnityApplication.dataPath .. "/../../../Product/Temp/LocalDirApp" local LaunchTestDirDoc = UnityApplication.dataPath .. "/../../../Product/Temp/LocalDirDoc" XLaunchFileModule.LaunchTestDirDoc = LaunchTestDirDoc local InitDocumentIndexTest function XLaunchFileModule.Check(resFileType, appPathModule, appVersionModule, completeCb,progressCb,exitCb) ResFileType = resFileType AppPathModule = appPathModule AppVersionModule = appVersionModule OnCompleteCallback = completeCb OnProgressCallback = progressCb OnExitCallback = exitCb ApplicationFilePath = AppPathModule.GetApplicationFilePath() DocumentFilePath = AppPathModule.GetDocumentFilePath() DocumentUrl = AppPathModule.GetDocumentUrl() DocumentIndexDir = DocumentFilePath .. "/" .. ResFileType .. "/" DocumentIndexPath= DocumentIndexDir .. INDEX NeedUpdate = false NeedShowSelect = false if ResFileType == RES_FILE_TYPE.LAUNCH_MODULE then NeedUpdate = AppVersionModule.CheckLaunchModuleUpdate() HasUpdated = AppVersionModule.HasLaunchModuleUpdated() NewVersion = AppVersionModule.GetNewLaunchModuleVersion() elseif ResFileType == RES_FILE_TYPE.MATRIX_FILE then NeedUpdate = AppVersionModule.CheckDocUpdate() HasUpdated = AppVersionModule.HasDocUpdated() NewVersion = AppVersionModule.GetNewDocVersion() if IsDlcBuild then NeedShowSelect = XLaunchDlcManager.NeedShowSelect(CsInfo.Version) -- 每个大版本只会弹出一次选择更新,小更新沿用选择结果 end end if CS.XRemoteConfig.IsHideFunc then --NeedUpdate = false end CsLog.Debug("[Download] 开始检查更新 NeedUpdate:"..tostring(NeedUpdate)..", type:"..ResFileType .. ", NeedShowSelect:" ..tostring(NeedShowSelect) .. ", IsDlcBuild:" .. tostring(IsDlcBuild)) if IsInGame or NeedLaunchTest then NeedUpdate = true ResolveResIndex() return end CheckIndexFile() end function XLaunchFileModule.SetIsInGame(isInGame) IsInGame = isInGame end -- function XLaunchFileModule.GetOffset() -- return OFFSET -- end DownloadDlcIndexs = function(cb) if not IsDlcBuild then cb() return end if not DocumentIndexTable then DocumentIndexTable, DlcIndexTable = LoadIndexTableWithDlcInfo(DocumentIndexPath) end local count = 0 local totalCount = 0 if DlcIndexTable then for _, _ in pairs(DlcIndexTable) do totalCount = totalCount + 1 end end if totalCount > 0 then CsGameEventManager:Notify(CS.XEventId.EVENT_LAUNCH_START_DOWNLOAD, totalCount, false, CsApplication.GetText("UpdateIndex") .. "(%d/%d)") -- 检查更新(0/10) CsApplication.SetProgress(0) CsApplication.SetMessage(CsApplication.GetText("CheckDlcIndex"))--"分析资源..." end local iter, t, key = pairs(DlcIndexTable) local info local iterKey = nil local Loop Loop = function() key, info = iter(t, iterKey) if not key then CsApplication.SetProgress(1) cb() return end local id = key local name = info[1] local sha1 = info[2] local cache = true -- 本地缓存 校验通过不重复下载 local url = string.format("%s/%s/%s/%s", DocumentUrl, NewVersion, ResFileType, name) local path = DocumentFilePath .. "/" .. ResFileType .. "/" .. name local downloader = CS.XUriPrefixDownloader(url, path, cache, sha1, TIMEOUT, RETRY, READ_TIMEOUT) local size = 0 --CsLog.Debug("DocumentUrl:"..DocumentUrl) --CsLog.Debug("url:"..url) --CsLog.Debug("path:"..path) CsTool.WaitCoroutinePerFrame(downloader:Send(), function(isComplete) if not isComplete then -- else if downloader.State ~= CS.XDownloaderState.Success then local msg = "XFileManager Download error, state error, state: " .. tostring(downloader.State) CsLog.Error(msg) local dict = {} dict.file_name = name dict.file_size = 1 DoRecord(dict, "80007", "XFileManagerDownloadError") ShowStartErrorDialog("FileManagerInitFileTableDownloadError", CsApplication.Exit, function() Loop() end, CsApplication.GetText("Retry")) -- 重试 return end count = count + 1 CsApplication.SetProgress(count / totalCount) -- CsLog.Debug("[] EVENT_LAUNCH_START_DOWNLOAD count:" .. tostring(count)) iterKey = key Loop() end end) end Loop() end -- 检测资源列表文件 CheckIndexFile = function() CS.XAppEventManager.LogAppEvent(CS.XAppEventConfig.Version_Checking_Start) local documentFilePath = DocumentFilePath .. "/" .. ResFileType .. "/" .. INDEX local keepLocalIndex = CS.System.IO.File.Exists(DocumentFilePath .. "/DevelopmentIndex") -- 用于Release环境不清理本地index文件(兼顾覆盖安装和手动放资源的情况) CsLog.Debug("[Download] CheckIndexFile:"..ResFileType .. ", documentFilePath:" .. tostring(CS.System.IO.File.Exists(documentFilePath)) .. ", Debug:" .. tostring(CsRemoteConfig.Debug) .. ", NeedUpdate:" .. tostring(NeedUpdate) .. ", keepLocalIndex:" .. tostring(keepLocalIndex)) if not NeedUpdate then if CS.System.IO.File.Exists(documentFilePath) and not CsRemoteConfig.Debug then -- debug情况下不需更新但要保留本地index if not keepLocalIndex then CS.XFileTool.DeleteFile(documentFilePath) end end -- 原始版本,直接进 ResolveResIndex() return end -- 下载/检测 当前index文件是否最新 local sha1 = "empty" local newVersion = "" if ResFileType == RES_FILE_TYPE.LAUNCH_MODULE then sha1 = CsRemoteConfig.LaunchIndexSha1 newVersion = CsRemoteConfig.LaunchModuleVersion elseif ResFileType == RES_FILE_TYPE.MATRIX_FILE then sha1 = CsRemoteConfig.IndexSha1 newVersion = CsRemoteConfig.DocumentVersion end if HasUpdated then local isCorrect = CS.XFileTool.CheckSha1(documentFilePath, sha1) CsLog.Debug("[Download] HasUpdated:" .. tostring(HasUpdated) .. ", isCorrect:" .. tostring(isCorrect)) if isCorrect then ResolveResIndex() return end end --CsLog.Debug("index download DocumentUrl:"..DocumentUrl) local uriPrefixStr = DocumentUrl .. "/" .. newVersion .. "/" .. ResFileType .. "/" .. INDEX local downloader = CS.XUriPrefixDownloader(uriPrefixStr, documentFilePath, false, sha1) CsTool.WaitCoroutine(downloader:Send(), function() if downloader.State ~= CS.XDownloaderState.Success then ShowStartErrorDialog("FileManagerInitVersionDownLoadError") else if ResFileType == RES_FILE_TYPE.LAUNCH_MODULE then AppVersionModule.UpdateLaunchVersion() ResolveResIndex() elseif ResFileType == RES_FILE_TYPE.MATRIX_FILE then AppVersionModule.UpdateDocVersion() ResolveResIndex() end end end) end -- {[assetPath] = value{[1] = Name, [2] = Sha1, [3] = Size}, ... } LoadIndexTable = function(indexPath) if NeedLaunchTest then if not CS.System.IO.File.Exists(indexPath) then return {} end end local assetBundle = CS.UnityEngine.AssetBundle.LoadFromFile(indexPath) if (assetBundle and assetBundle:Exist()) then local assetName = assetBundle:GetAllAssetNames()[0] local asset = assetBundle:LoadAsset(assetName, typeof(CS.UnityEngine.TextAsset)) local indexFile = XMessagePack.Decode(asset.bytes) local indexTable = indexFile[1] assetBundle:Unload(true) return indexTable end return nil end LoadIndexTableWithDlcInfo = function(indexPath) local assetBundle = CS.UnityEngine.AssetBundle.LoadFromFile(indexPath) if (assetBundle and assetBundle:Exist()) then local assetName = assetBundle:GetAllAssetNames()[0] local asset = assetBundle:LoadAsset(assetName, typeof(CS.UnityEngine.TextAsset)) local indexFile = XMessagePack.Decode(asset.bytes) local indexTable = indexFile[1] local dlcIndexTable = indexFile[2] or {} assetBundle:Unload(true) return indexTable, dlcIndexTable end return nil end local SetDlcTable -- 解析doc目录下index InitDocumentIndex = function() if NeedLaunchTest then InitDocumentIndexTest() else if not CS.System.IO.File.Exists(DocumentIndexPath) then CsLog.Error("[Download] Init DocumentIndex Failed, file not exist: " .. tostring(DocumentIndexPath)) return end if not DocumentIndexTable then if IsDlcBuild then DocumentIndexTable, DlcIndexTable = LoadIndexTableWithDlcInfo(DocumentIndexPath) else DocumentIndexTable = LoadIndexTable(DocumentIndexPath) -- {[assetPath] = value{[1] = Name, [2] = Sha1, [3] = Size}, ... } end end end CurrentFileTable = {} -- 当前需下载资源 AllFileTableDlc = {} -- DLC完整资源 local countApp = 0 local countExist = 0 NeedFileSet = {} -- 需下载标记 DlcNeedFileMap = {} -- DLC id对应所需资源 local countAll = 0 -- 基础补丁 for asset, info in pairs(DocumentIndexTable) do countAll = countAll + 1 NeedFileSet[info[1]] = true CurrentFileTable[asset] = info AllFileTableDlc[asset] = info end -- 统计资源 if IsDlcBuild then if ResFileType == RES_FILE_TYPE.MATRIX_FILE and DlcIndexTable then XLaunchDlcManager.Init(DlcIndexTable) XLaunchDlcManager.SetDlcIndexInfo(DLC_BASE_INDEX, DocumentIndexTable) -- 使用新分包构建方式后,暂时没有通用资源包了,设置为空 XLaunchDlcManager.SetDlcIndexInfo(DLC_COMMON_INDEX, {}) local dlcUseAppCount = 0 local dlcTableMap = {} -- 游戏内下载用 local needDownloadMap = {} -- 调试用 local checkFullDownload = IsFullDownloadSelectType() local isSelectFull = true if not IsInGame then --非游戏内 -- 1:基础资源 2:完整资源 local downloadMode = XLaunchDlcManager.IsFullDownload(CsInfo.Version) and 2 or 1 isSelectFull = downloadMode == 2 end -- 分包补丁 for dlcId, dlcTable in pairs(DlcIndexTable) do dlcTableMap[dlcId] = dlcTable XLaunchDlcManager.SetDlcIndexInfo(dlcId, dlcTable) local needDownloadDlc = (isSelectFull and XLaunchDlcManager.CheckNeedDownload(dlcId, NeedShowSelect)) or checkFullDownload needDownloadMap[dlcId] = needDownloadDlc local fileMap = {} for asset, info in pairs(dlcTable) do NeedFileSet[info[1]] = true if ApplicationIndexTable[asset] and ApplicationIndexTable[asset][1] == info[1]then dlcUseAppCount = dlcUseAppCount + 1 else if needDownloadDlc then CurrentFileTable[asset] = info end AllFileTableDlc[asset] = info fileMap[info[1]] = info end end DlcNeedFileMap[dlcId] = fileMap end SetDlcTable(dlcTableMap) if IsDebugBuild then local logTab = {} for dlcId, need in pairs(needDownloadMap) do table.insert(logTab, dlcId .. ":" .. tostring(need)) end CsLog.Debug("[DLC] needDownloadMap: " .. tostring(table.concat(logTab, "\n"))) end end -- 剔除包内已有资源(需asset与Name都对应) for asset, info in pairs(ApplicationIndexTable) do local value = AllFileTableDlc[asset] countApp = countApp + 1 if value and value[1] == info[1] then countExist = countExist + 1 AllFileTableDlc[asset] = nil CurrentFileTable[asset] = nil end end else CurrentFileTable = DocumentIndexTable -- 剔除包内已有资源(需asset与Name都对应) for asset, info in pairs(ApplicationIndexTable) do countApp = countApp + 1 local value = CurrentFileTable[asset] if value and value[1] == info[1] then countExist = countExist + 1 CurrentFileTable[asset] = nil end end end CsLog.Debug("[Download] 基础资源总量:" .. countAll .. ",app包内资源数量(记录/存在):" .. countApp .. "/" .. countExist) end SetDlcTable = function(dlcTableMap) local documentFilePath = DocumentFilePath .. "/" .. ResFileType .. "/" if NeedLaunchTest then documentFilePath = LaunchTestDirDoc .. "/" .. ResFileType .. "/" end local needLog = IsDebugBuild and CS.UnityEngine.Application.platform == CS.UnityEngine.RuntimePlatform.WindowsEditor local DownloadedMark = {} local logTab = {} for dlcId, dlcTable in pairs(dlcTableMap) do local count, clearCount, downloadedCount = 0, 0, 0 local size, clearSize, downloadedSize = 0, 0, 0 for asset, info in pairs(dlcTable) do count = count + 1 size = size + info[3] local name = info[1] local value = ApplicationIndexTable[asset] if value and value[1] == name then -- 包内 clearCount = clearCount + 1 clearSize = clearSize + info[3] dlcTable[asset] = nil -- 不统计到总大小 elseif needLog then if DownloadedMark[name] == nil then DownloadedMark[name] = CS.System.IO.File.Exists(documentFilePath .. name) -- 已下载 end if DownloadedMark[name] then local downloaded = DownloadedMark[name] downloadedCount = downloadedCount + 1 downloadedSize = downloadedSize + info[3] end end end if IsDebugBuild then table.insert(logTab, "[DLC] DLC .." .. dlcId .. ", appb包内 + doc已下载 = 总 - 余量,数量" .. clearCount .. " + " .. downloadedCount.. " = " .. count .. " - " .. (count-clearCount-downloadedCount) .. ", 大小: " .. math.ceil(clearSize/1024/1024) .."mb" .. " + " .. math.ceil(downloadedSize/1024/1024) .. "mb" .. " = " .. math.ceil(size/1024/1024) .. "mb" .. " - " .. math.ceil((size - clearSize - downloadedSize)/1024/1024) .. "mb)") end XLaunchDlcManager.SetDlcIndexInfo(dlcId, dlcTable) -- 记录总需下载资源 end if IsDebugBuild and #logTab > 0 then CsLog.Debug("DLC各分包下载情况:\n" .. table.concat(logTab, "\n")) end DownloadedMark = nil end ResolveResIndex = function() CS.XAppEventManager.LogAppEvent(CS.XAppEventConfig.Version_Checking_End) local applicationIndexPath = ApplicationFilePath .. "/" .. ResFileType .. "/" .. INDEX if NeedLaunchTest and IsDlcBuild then applicationIndexPath = LaunchTestDirApp .. "/" .. ResFileType .. "/" .. INDEX end ApplicationIndexTable = LoadIndexTable(applicationIndexPath) CsLog.Debug("[Download] ResolveResIndex. NeedUpdate:" .. tostring(NeedUpdate) .. ", applicationIndexPath:" .. applicationIndexPath .. ", documentIndexPath:" .. DocumentIndexPath) if not NeedUpdate then -- 原始版本 if CS.System.IO.File.Exists(DocumentIndexPath) then CsLog.Debug("Local index:" .. DocumentIndexPath) InitDocumentIndex() HasLocalFiles = true end OnCompleteResFilesInit() -- 无需更新,直接完成 return end InitDocumentIndex() UpdateSize = 0 UpdateTableCount = 0 UpdateTable = {} for _, info in pairs(CurrentFileTable) do if UpdateTable[info[1]] then local dict = {} dict["file_name"] = info[1] DoRecord(dict, "80006", "UpdateTableAddFileError") CsLog.Error("repeat update file:" .. tostring(info[1])) ShowStartErrorDialog("FileManagerInitFileTableUpdateTableError") return end UpdateTable[info[1]] = info UpdateTableCount = UpdateTableCount + 1 UpdateSize = UpdateSize + info[3] end AllUpdateSize = 0 AllUpdateTable = {} AllUpdateTableCount = 0 if IsDlcBuild then for _, info in pairs(AllFileTableDlc) do AllUpdateTable[info[1]] = info AllUpdateTableCount = AllUpdateTableCount + 1 AllUpdateSize = AllUpdateSize + info[3] end end CsLog.Debug(string.format("[Download] UpdateSize: %d(mb), UpdateTableCount: %d, AllUpdateSize: %d(mb), AllUpdateTableCount: %d", math.ceil(UpdateSize/1024/1024), UpdateTableCount, math.ceil(AllUpdateSize/1024/1024), AllUpdateTableCount)) local deleteKey = SPECIAL_DELETE_MATRIX_PREF_KEY .. tostring(AppVersionModule.GetAppVersion()) local isMatrix = ResFileType == RES_FILE_TYPE.MATRIX_FILE local cleanFlag = CS.UnityEngine.PlayerPrefs.GetInt(deleteKey, 0) local checkClean = (isMatrix and (not cleanFlag or cleanFlag ~= 1)) local isForceClean = ForceVersion[CsInfo.Version] if isMatrix and not isForceClean then -- 补充强删资源逻辑 local theDeleteKey = SPECIAL_DELETE_MATRIX_PREF_KEY .. "1." .. ForceVersionNum .. ".0" local theCleanFlag = CS.UnityEngine.PlayerPrefs.GetInt(theDeleteKey, 0) CsLog.Debug("key:" .. theDeleteKey .. ", cleanFlag:" .. tostring(cleanFlag) .. ", force cleanFlag :" .. tostring(theCleanFlag)) if cleanFlag ~= 1 and (theCleanFlag ~= 1) then -- 首次检测当前版本、 且没经历过强删版本 for versionNum = ForceVersionNum - 1, 10, -1 do -- 经历过再之前版本 -- 属于旧包覆盖安装,需要强清资源 local lastDeleteKey = SPECIAL_DELETE_MATRIX_PREF_KEY .. "1." .. versionNum .. ".0" local lastCleanFlag = CS.UnityEngine.PlayerPrefs.GetInt(lastDeleteKey, 0) CsLog.Debug("[Download] Check Force Clean Key:" .. lastDeleteKey .. ", cleanFlag:" .. tostring(lastCleanFlag) .. ", " .. type(lastCleanFlag)) if lastCleanFlag == 1 then isForceClean = true CsLog.Debug("[Download] 过旧版本 需要全面清理资源, version:" .. lastDeleteKey) -- 完成后增加强删版本的标记 CS.UnityEngine.PlayerPrefs.SetInt(theDeleteKey, 1) CS.UnityEngine.PlayerPrefs.Save() break end end end end CsLog.Debug("[Download] 上一版本资源key: " .. tostring(deleteKey) .. ", type: " .. tostring(ResFileType) .. ", checkClean: " .. tostring(checkClean) .. ", force:" .. tostring(isForceClean) .. ", CsInfo.Version:" .. tostring(CsInfo.Version)) local files if NeedLaunchTest then files = CS.XFileTool.GetAllFiles(LaunchTestDirDoc .. "/" .. ResFileType) else files = CS.XFileTool.GetFiles(DocumentFilePath .. "/" .. ResFileType) end local lastVerCount = 0 local otherCount = 0 local totalCount = 0 --是否启用IOS后台下载 --在启用时,由于IOS校验流程的统一需要,因此文件下载完可能还未校验,需要假设资源是完整的 --在以上条件下,需要合理估计仍然需要下载的文件大小,因此需要减去对仅未验证的文件的大小 local isUseIosDownloadService = (CS.XRemoteConfig.DownloadMethod == 0) and AppPathModule.IsIos() DownloadedMap = {} for i = 0, files.Count - 1 do local file = files[i] local name = CS.XFileTool.GetFileName(file) totalCount = totalCount + 1 local isIndex = IsDlcBuild and (string.sub(name,1,5) == INDEX) or (name == INDEX) if isIndex then goto CONTINUE end if checkClean then if isForceClean or NeedFileSet[name] == nil then CsLog.Debug("[Download] 清理上一版本资源" .. tostring(name) .. ", need:" .. tostring(NeedFileSet[name] ~= nil)) CS.XFileTool.DeleteFile(file) lastVerCount = lastVerCount + 1 goto CONTINUE end end -- 检查更新文件是否存在 local hasUpdated = false local info = UpdateTable[name] if info then UpdateTable[name] = nil UpdateTableCount = UpdateTableCount - 1 UpdateSize = UpdateSize - info[3] hasUpdated = true end if IsDlcBuild then local infoDlc = AllUpdateTable[name] if infoDlc then AllUpdateTable[name] = nil AllUpdateTableCount = AllUpdateTableCount - 1 AllUpdateSize = AllUpdateSize - infoDlc[3] DownloadedMap[name] = true hasUpdated = true end end if hasUpdated then goto CONTINUE end local nameWithOutExtension = CS.XFileTool.GetFileNameWithoutExtension(file) if UpdateTable[nameWithOutExtension] then -- 下载时临时文件(name.download)将会保留 info = UpdateTable[nameWithOutExtension] if isUseIosDownloadService then if CS.XFileTool.GetFileExtension(file) == UNCHECKED_FILE_EXTENSION then UpdateSize = UpdateSize - info[3] end end goto CONTINUE end otherCount = otherCount + 1 CsLog.Debug("[Download] .. other Clean:" .. tostring(file)) CS.XFileTool.DeleteFile(file) :: CONTINUE :: end CsLog.Debug(string.format("[Download] 资源清理 本地总数:%d, 清理上版本数:%d, 其他清理:%d", totalCount, lastVerCount, otherCount)) CsLog.Debug(string.format("[Download] 准备下载,本次需下载数: %d(%dmb), dlc未下载:%d(%dmb)", UpdateTableCount, math.ceil(UpdateSize/1024/1024), AllUpdateTableCount, math.ceil(AllUpdateSize/1024/1024))) if checkClean then CsLog.Debug("[Download] 清理上一版本资源完成。") CS.UnityEngine.PlayerPrefs.SetInt(deleteKey, 1) CS.UnityEngine.PlayerPrefs.Save() end if IsDlcBuild and isMatrix then XLaunchDlcManager.SetDownloadedMap(DownloadedMap) CheckFixDlcRecord() end PrepareDownload() end local GetDlcMapCountSize = function(map) local num = 0 local size = 0 for _, info in pairs(map) do num = num + 1 size = size + info[3] end return num, size end -- 检查dlc文件是否存在 CheckFixDlcRecord = function() if IsInGame then return end local nums = {} local sizes = {} if IsDebugBuild then -- 总况 for dlcId, map in pairs(DlcNeedFileMap) do local num, size = GetDlcMapCountSize(map) nums[dlcId] = num sizes[dlcId] = size end end local logTab = {} -- 剔除通用 DlcNeedFileMap[DLC_COMMON_INDEX] = nil -- 剔除已下载 for dlcId, map in pairs(DlcNeedFileMap) do local num, num2, num3, size = 0, 0, 0, 0 for name, info in pairs(map) do num2 = num2 + 1 if DownloadedMap[name] then map[name] = nil num = num + 1 size = size + info[3] else num3 = num3 + 1 end end if IsDebugBuild then table.insert(logTab, "dlc " .. dlcId .. ", 已下载数量:" .. num .. "(总" .. num2 .. " - 未下载" .. num3 .. "), 已下载大小:".. math.ceil(size/1024/1024).."mb") end end if IsDebugBuild then CsLog.Debug("[DLC] ==== dlc检测前剔除 " .. table.concat(logTab, "\n")) end -- 修正下载记录 for dlcId, map in pairs(DlcNeedFileMap) do local downloaded = XLaunchDlcManager.HasDownloadedDlc(dlcId) if downloaded then if next(map) then if IsDebugBuild then local num, size = GetDlcMapCountSize(map) CsLog.Error("[DLC]dlc_" .. tostring(dlcId) .. "检测异常:记录为已下载,但缺失本地文件,修正为未下载,需下载数量:" .. num .. "/" .. tostring(nums[dlcId]) ..", ".. math.ceil(size/1024/1024) .. "/" .. math.ceil(sizes[dlcId]/1024/1024) .."mb" .. ',' .. size .. "/" .. sizes[dlcId]) else CsLog.Error(dlcId .. "记录:[已下载],但仍需下载,修复为:[未下载]") end XLaunchDlcManager.FixDownloadedDlc(dlcId, false) elseif IsDebugBuild then CsLog.Debug("[DLC]dlc_" .. tostring(dlcId) .. "检测ok,全部下载数量:" .. tostring(nums[dlcId])) end else if not next(map) then if IsDebugBuild then CsLog.Error("[DLC]dlc_" .. tostring(dlcId) .. "检测异常:记录为未下载,但已下载完成,修正记录。数量:" .. tostring(nums[dlcId])) else CsLog.Error(dlcId .. "记录[未下载],但无需下载,修复为[已下载]") end XLaunchDlcManager.FixDownloadedDlc(dlcId, true) elseif IsDebugBuild then local num, size = GetDlcMapCountSize(map) CsLog.Debug("[DLC]dlc_" .. tostring(dlcId) .. "检测ok,未下载数量:" .. num .. "/" .. tostring(nums[dlcId]) ..", ".. math.ceil(size/1024/1024) .. "/" .. math.ceil(sizes[dlcId]/1024/1024) .."mb") end end end CsLog.Debug("[DLC] 检查DLC资源完成。") end local GetSizeAndUnit = function(size) local unit = "k" local num = size / 1024 if (num > 100) then unit = "MB" num = num / 1024 end return unit,num end local InitFullDownload = function() XLaunchDlcManager.SetAllLaunchDownloadRecord() UpdateTable = AllUpdateTable UpdateSize = AllUpdateSize end local OnDoneSelect = function(isFullDownload) XLaunchDlcManager.DoneSelect(CsInfo.Version) XLaunchDlcManager.SetIsFullDownload(CsInfo.Version, isFullDownload) if isFullDownload then InitFullDownload() else if UpdateTableCount <= 0 then OnCompleteResFilesInit() return end end DoPrepareDownload() end PrepareDownload = function() CsLog.Debug("PrepareDownload, UpdateTableCount:" .. UpdateTableCount .. ", NeedShowSelect:" .. tostring(NeedShowSelect) .. ", AllUpdateTableCount:" .. AllUpdateTableCount .. ", IsInGame:"..tostring(IsInGame)) if UpdateTableCount <= 0 and (not NeedShowSelect or AllUpdateTableCount <=0) then OnCompleteResFilesInit() return end --todo 如果是dlc打包,显示选择框,选择完重新下载 if not IsInGame and NeedShowSelect then OnNotifyEvent = function(evt, data) OnDoneSelect(data[0]) end CsGameEventManager:RegisterEvent(CS.XEventId.EVENT_LAUNCH_DONE_DOWNLOAD_SELECT, OnNotifyEvent) CsGameEventManager:Notify(CS.XEventId.EVENT_LAUNCH_SHOW_DOWNLOAD_SELECT,UpdateSize,AllUpdateSize) else DoPrepareDownload() end end DoPrepareDownload = function() -- 分包且禁用,则全部下载 if IsDlcBuild and IsFullDownloadSelectType() then InitFullDownload() end -- 1:基础资源 2:完整资源 local downloadMode = XLaunchDlcManager.IsFullDownload(CsInfo.Version) and 2 or 1 local dict = {["type"] = ResFileType, ["version"] = NewVersion, ["size"] = UpdateSize, ["mode"] = downloadMode } DoRecord(dict, "80011", "StartDownloadNewFiles") local unit,num = GetSizeAndUnit(UpdateSize) -- todo updateSize算上launch+matrix,只需launch弹出一次 if ResFileType == RES_FILE_TYPE.MATRIX_FILE and not IsInGame and not TipsOnce then TipsOnce = true local sizeTxt = string.format("%0.2f%s", num, unit) local envTxt = "" local totalTxt = CsApplication.GetText("UpdateTips") if UnityApplication.internetReachability == CS.UnityEngine.NetworkReachability.ReachableViaCarrierDataNetwork then envTxt = CsApplication.GetText("CarrierTxt") else envTxt = CsApplication.GetText("WifiTxt") end CS.XHeroBdcAgent.BdcUpdateGame("203", "1", "0") local tmpStr = string.format(totalTxt, sizeTxt, envTxt) local cancelCB = CsApplication.Exit -- CsTool.WaitCoroutine(CsApplication.CoDialog(CsApplication.GetText("Tip"), tmpStr, cancelCB, function() -- DownloadFiles() -- end)) CsGameEventManager:Notify(CS.XEventId.EVENT_LAUNCH_DIALOG, tmpStr, cancelCB, function() DownloadFiles() end) else DownloadFiles() end end local AndroidBackgroundDownload = function() --android background download todo --1.组建好一个数组,传给backgroud download组件,开始下载 --2.每帧获取下载状态,更新界面(当前下载文件,下载进度) --3.重试状态 --4.下载完成状态 local urlPrefix = string.format("%s/%s/%s/", DocumentUrl, NewVersion, ResFileType) local downloadDir = DocumentFilePath .. "/" .. ResFileType .. "/" local allNameTable = {} local allSha1Table = {} local allSizeTable = {} for name, info in pairs(UpdateTable) do table.insert(allNameTable, info[1]) table.insert(allSha1Table, info[2]) table.insert(allSizeTable, info[3]) end local names = table.concat(allNameTable,";") local sha1s = table.concat(allSha1Table,";") local sizes = table.concat(allSizeTable,";") CsDownloadService:Download(urlPrefix, downloadDir, names, sha1s, TIMEOUT, RETRY, sizes) local waitTimeCnt = 0 local updateInfoCb = nil local lastProgress = nil updateInfoCb = function() -- 下载进度 local state = CsDownloadService:GetDownloadState() local fileSize = CsDownloadService:GetCurrentFileSize() local curDoneSize = CsDownloadService:GetCurrentDownloadSize() if state == DownloadState.ING then waitTimeCnt = 0 local updateProgress = UpdateSize == 0 and 0 or curDoneSize / UpdateSize if updateProgress>1 then updateProgress =1 end CsApplication.SetProgress(updateProgress) if lastProgress ~= updateProgress and OnProgressCallback then lastProgress = updateProgress OnProgressCallback(updateProgress) end elseif state == DownloadState.FAIL or (state == DownloadState.NONE and waitTimeCnt > 20) then CsTool.RemoveUpdateEvent(updateInfoCb) local errMsg = CsDownloadService:GetExceptionInfo() local name = CsDownloadService:GetCurrentFileName() CsLog.Error("[Download] Android Download error, state error, state: " .. tostring(state)..", err:" .. errMsg .. ", name:" .. tostring(name) .. ", fileSize:" .. tostring(fileSize)) local exitCb = OnExitCallback or CsApplication.Exit CsLog.Debug("[Download Android Backgroud] Istate " .. tostring(state) .. ",waitTimeCnt: " .. tostring(waitTimeCnt)) ShowStartErrorDialog("FileManagerInitFileTableDownloadError", exitCb, function() RemoveEvents() CheckIndexFile() end, CsApplication.GetText("Retry")) elseif state == DownloadState.DONE then CsLog.Debug("[Download Android Backgroud] Istate == DownloadState.DONE! ") CsTool.RemoveUpdateEvent(updateInfoCb) CompleteDownload() elseif state == DownloadState.NONE then waitTimeCnt = waitTimeCnt + CS.UnityEngine.Time.deltaTime end end CsTool.AddUpdateEvent(updateInfoCb) end local IosBackgroundDownload = function() local urlPrefix = string.format("%s/%s/%s", DocumentUrl, NewVersion, ResFileType) CS.XIOSDownloadConfig.PrepareCNDList(urlPrefix); local taskArr = {} for _,v in pairs(UpdateTable) do table.insert(taskArr, string.format("%s %s %s", v[1], v[3], v[2])) end local taskInfo = table.concat(taskArr,"\n") CS.XIOSDownloadCustomer.Instance:SetTaskInfo(taskInfo) local manager = CS.XIOSDownloadManager.Instance local verifier = CS.XIOSDownloadVerifier.Instance local updateEvent local lastProgress = nil updateEvent = function() if manager.StateInt == IosDownloadState.PreparingLocalFiles then --Nothing Here elseif manager.StateInt == IosDownloadState.PreparingDownload then --Nothing Here elseif manager.StateInt == IosDownloadState.Downloading or manager.StateInt == IosDownloadState.AppendDownloading then if manager.StateInt == IosDownloadState.AppendDownloading and manager.TotalTaskBytes ~= 0 then CsGameEventManager:Notify(CS.XEventId.EVENT_LAUNCH_START_DOWNLOAD, manager.TotalTaskBytes) end local progress = manager.CurDownloadedBytes / manager.TotalTaskBytes; if progress and progress ~= math.huge and progress == progress then -- NAN用相等判断 CsApplication.SetProgress(progress) end if lastProgress ~= progress and OnProgressCallback then lastProgress = progress OnProgressCallback(progress) end elseif manager.StateInt == IosDownloadState.Verifying then CS.XGameEventManager.Instance:Notify(CS.XEventId.EVENT_LAUNCH_START_LOADING) CsApplication.SetMessage(string.format(CsApplication.GetText("Verifying"), verifier.CurrentCheckCount, verifier.TotalNeedCheckCount)) -- 正在校验中(%d/%d) CsApplication.SetProgress(verifier.CurrentCheckCount / verifier.TotalNeedCheckCount) elseif manager.StateInt == IosDownloadState.Finished then CsTool.RemoveUpdateEvent(updateEvent) manager:Clear() CompleteDownload() end end manager:Prepare() manager:SetDownloadErrorHandler(function(file) local exitCb = OnExitCallback or CsApplication.Exit ShowStartErrorDialog("FileManagerInitFileTableDownloadError", exitCb, function() manager:ContinueDownloading() end, CsApplication.GetText("Retry")) -- 重试 end) CsTool.AddUpdateEvent(updateEvent) end local TraditionalDownload = function() if ResFileType == RES_FILE_TYPE.LAUNCH_MODULE then for _, info in pairs(UpdateTable) do local name = info[1] local ext = CS.XFileTool.GetFileExtension(name) if string.find(ext, "usm") then CsApplication.SetMessage(CsApplication.GetText("PVDownloading")) -- "PV下载中..." break end end end local count = 0 -- local updateFileText = CsApplication.GetText("UpdateFile") local iter, t, key = pairs(UpdateTable) local info local iterKey = nil local Loop local useCache = true local lastProgress = nil local currentUpdateSize = 0 Loop = function() key, info = iter(t, iterKey) -- print((count + 1) .. "/" .. UpdateTableCount .. "、IsPause :" .. tostring(IsPause)) if IsPause then return end if not key then CompleteDownload() return end count = count + 1 local name = info[1] local sha1 = info[2] -- 补丁index中记录的sha1,和下载后文件sha1对比 local url = string.format("%s/%s/%s/%s", DocumentUrl, NewVersion, ResFileType, name) local path = DocumentFilePath .. "/" .. ResFileType .. "/" .. name -- CsApplication.SetMessage(updateFileText .. ": " .. name) if NeedLaunchTest then url = ResFileType .. "/" .. name path = LaunchTestDirDoc .. "/" .. ResFileType .. "/" .. name end local downloader = CS.XUriPrefixDownloader(url, path, useCache, sha1, TIMEOUT, RETRY, READ_TIMEOUT) CurrentDownloader = downloader local size = 0 CsTool.WaitCoroutinePerFrame(downloader:Send(), function(isComplete) if not isComplete then -- currentUpdateSize = currentUpdateSize + (downloader.CurrentSize - size) size = downloader.CurrentSize local updateProgress = UpdateSize == 0 and 0 or currentUpdateSize / UpdateSize CsApplication.SetProgress(updateProgress) if lastProgress ~= updateProgress and OnProgressCallback then lastProgress = updateProgress -- print("... process:" .. updateProgress .. ", currentUpdateSize/UpdateSize:" .. math.ceil(currentUpdateSize/1024/1024) .."mb/" .. math.ceil(UpdateSize/1024/1024) .."mb, ".. currentUpdateSize .. "/" .. UpdateSize) OnProgressCallback(updateProgress) end else if downloader.State ~= CS.XDownloaderState.Success then if downloader.State == CS.XDownloaderState.Stop then CsLog.Debug("Stop Downloading.") return end local msg = "[Download] error, state error, state: " .. tostring(downloader.State) CsLog.Error(msg) local dict = {} dict.file_name = name dict.file_size = info[3] DoRecord(dict, "80007", "XFileManagerDownloadError") local exitCb = OnExitCallback or CsApplication.Exit local errorCode = IsInGame and "FileManagerInitFileTableInGameDownloadError" or "FileManagerInitFileTableDownloadError" ShowStartErrorDialog(errorCode, exitCb, function() Loop() end, CsApplication.GetText("Retry")) -- 重试 return end if IsDlcBuild then XLaunchDlcManager.SetDownloadedFile(name, true) end currentUpdateSize = currentUpdateSize - size + downloader.Size iterKey = key Loop() end end) end Loop() end local ParallelDownload = function() local lastProgress = nil local downloadManager = CS.XNewDownloadManager downloadManager.Init() downloadManager.Prepare() -- downloadManager.AddWatcher() for _name, info in pairs(UpdateTable) do local name = info[1] local sha1 = info[2] -- 补丁index中记录的sha1,和下载后文件sha1对比 local url = string.format("%s/%s/%s/%s", DocumentUrl, NewVersion, ResFileType, name) local path = DocumentFilePath .. "/" .. ResFileType .. "/" .. name downloadManager.AppendTask(url, path, info[3], sha1) end local DownloadState = CS.XDownloadManagerState local progress = CS.XDownloadProgress local exitCb = OnExitCallback or CsApplication.Exit local updateFunc updateFunc = function() if downloadManager.State == DownloadState.Downloading then local p = progress.CurrentDownloadSize / progress.TotalDownloadSize CsApplication.SetProgress(p) if lastProgress ~= p and OnProgressCallback then lastProgress = p OnProgressCallback(p) end elseif downloadManager.State == DownloadState.CompleteError then CsTool.RemoveUpdateEvent(updateFunc) ShowStartErrorDialog("FileManagerInitFileTableDownloadError", exitCb, function() downloadManager.RePrepareFailedTask() CsGameEventManager:Notify(CS.XEventId.EVENT_LAUNCH_START_DOWNLOAD, progress.TotalDownloadSize) downloadManager.Start() CsTool.AddUpdateEvent(updateFunc) end, CsApplication.GetText("Retry")) -- 重试 elseif downloadManager.State == DownloadState.Complete then CsTool.RemoveUpdateEvent(updateFunc) downloadManager.Stop() CompleteDownload() else return end end CsGameEventManager:Notify(CS.XEventId.EVENT_LAUNCH_START_DOWNLOAD, progress.TotalDownloadSize) downloadManager.SetTaskFinish() downloadManager.Start() CsTool.AddUpdateEvent(updateFunc) end -- 是否需要播放cg(名字+大版本号) local function CheckPlayCG() if IsInGame then return end local needCGBtn = (ResFileType == RES_FILE_TYPE.MATRIX_FILE) local needPlayCG = false local videoUrl = "null" if needCGBtn then videoUrl = CS.XAudioManager.LaunchVideoAsset local hasVideo = (videoUrl ~= "" and videoUrl ~= "null") if hasVideo then local videoName = CS.XFileTool.GetFileNameWithoutExtension(videoUrl) local newRecord = videoName .. "_" .. tostring(AppVersionModule.GetAppVersion()) local oldRecord = CS.UnityEngine.PlayerPrefs.GetString(LAUNCH_PLAYED_CG, "") if newRecord ~= oldRecord then CS.UnityEngine.PlayerPrefs.SetString(LAUNCH_PLAYED_CG, newRecord) needPlayCG = true end local bundleName = CS.XResourceManager.GetBundleUrl(videoUrl); videoUrl = CS.XBundleManager.GetFile(bundleName) if not videoUrl then needCGBtn = false else if CS.UnityEngine.Application.platform == CS.UnityEngine.RuntimePlatform.Android then local path = videoUrl local streamingAssetPath = CS.UnityEngine.Application.streamingAssetsPath local len = string.len(streamingAssetPath) local prefix = string.sub(videoUrl, 0, len) -- 若pv在包内,对路径修正为 resource/launch/xxx.usm if prefix == streamingAssetPath then videoUrl = string.sub(videoUrl, len + 2) end end end print("[Audio] Need Play CG, newRecord:" .. tostring(newRecord) .. ", oldRecord:" .. tostring(oldRecord) .. ", videoUrl:" .. tostring(videoUrl)) else needCGBtn = false end print("[Audio] Need Play CG:" .. tostring(needPlayCG) .. ", hasVideo:" .. tostring(hasVideo) .. ", videoUrl:" .. tostring(videoUrl)) end CsGameEventManager:Notify(CS.XEventId.EVENT_LAUNCH_CG, needCGBtn, needPlayCG, videoUrl) end DownloadFiles = function() CsGameEventManager:Notify(CS.XEventId.EVENT_LAUNCH_START_DOWNLOAD, UpdateSize) CheckPlayCG() CS.XAppEventManager.LogAppEvent(CS.XAppEventConfig.Resource_Download_Start) -- -- 如果空间不足的话,直接弹出空间不足提示 -- if UpdateSize > 0 and not CS.XAppPlatBridge.DiskSizeEnough(math.ceil(UpdateSize/1024)) then -- ShowStartErrorDialog("FileManagerDownloadDiskFull") -- return -- end CS.XHeroBdcAgent.BdcUpdateGame("204", "1", "0") CsApplication.SetMessage("") -- CsApplication.GetText("GameUpdate") CsApplication.SetProgress(0) local isUseAndroidDownloadService = (CS.XRemoteConfig.DownloadMethod == 0) and AppPathModule.IsAndroid() local isUseIosDownloadService = (CS.XRemoteConfig.DownloadMethod == 0) and AppPathModule.IsIos() local useParallel = (CS.XRemoteConfig.ParallelQueueSize ~= nil and CS.XRemoteConfig.ParallelDownload == 1) if CS.XRemoteConfig.ParallelQueueSize ~= nil and useParallel and ResFileType == RES_FILE_TYPE.MATRIX_FILE and not IsInGame then CsLog.Debug("多线程下载模式") ParallelDownload() return end if isUseAndroidDownloadService and ResFileType == RES_FILE_TYPE.MATRIX_FILE and not IsInGame then CsLog.Debug("安卓后台下载模式") AndroidBackgroundDownload() elseif isUseIosDownloadService and ResFileType == RES_FILE_TYPE.MATRIX_FILE and not IsInGame then CsLog.Debug("IOS后台下载模式") IosBackgroundDownload() else CsLog.Debug("传统下载模式") TraditionalDownload() end end function XLaunchFileModule.PauseDownload() if CurrentDownloader then CurrentDownloader:Stop() CurrentDownloader = nil end IsPause = true CompleteDownload() --需要在CompleteDownload之后 XLaunchDlcManager.ClearGameDownloadRecord() end function XLaunchFileModule.ResumeDownload() IsPause = false end function XLaunchFileModule.CleanDlcFiles(dlcId) if dlcId == DLC_BASE_INDEX or dlcId == DLC_COMMON_INDEX then CsLog.Error("[DLC] 清理dlc资源失败 dlcId:" .. tostring(dlcId)) return end local dirPath = DocumentFilePath .. "/" .. ResFileType .. "/" if NeedLaunchTest then dirPath = LaunchTestDirDoc .. "/" .. ResFileType .. "/" end local fileMap = DlcNeedFileMap[dlcId] if not fileMap then CsLog.Error("[DLC] 清理dlc资源失败 fileMap is ni, dlcId:" .. tostring(dlcId)) return end local count, size = 0, 0 for name, info in pairs(fileMap) do local file = dirPath .. name CS.XFileTool.DeleteFile(file) XLaunchDlcManager.SetDownloadedFile(name, false) count = count + 1 size = size + info[3] end if IsDebugBuild then CsLog.Debug("[DLC] 清理DLC .." .. dlcId .. "下载资源,数量:" .. count .. ",大小:" .. math.ceil(size/1024/1024) .. "mb") end end -- 启动下载测试 InitDocumentIndexTest = function() local indexPath = LaunchTestDirDoc .. "/" .. ResFileType .. "/" .. INDEX print("[DownloadTest] InitDocumentIndexTest: ResFileType: " .. ResFileType .. ", indexPath:" .. indexPath) if CS.System.IO.File.Exists(indexPath) then -- 本地下载release测试(真机逻辑解析index) print("[DownloadTest] 本地下载-release测试(解析index), IsDlcBuild:" .. tostring(IsDlcBuild)) if IsDlcBuild then DocumentIndexTable, DlcIndexTable = LoadIndexTableWithDlcInfo(indexPath) else print("[DownloadTest] InitDocumentIndexTest:222") DocumentIndexTable = LoadIndexTable(DocumentIndexPath) end else -- 本地下载(随意文件)测试 print("[DownloadTest] 本地下载-随意文件测试") DocumentIndexTable = {} local UnityApplication = CS.UnityEngine.Application local cdnPath = LaunchTestPath .. "/" .. ResFileType local files = CS.XFileTool.GetAllFiles(cdnPath) local function GetFileSize(path) local file, err = io.open(path, "rb") if not file then return 0 end local size = file:seek("end") file:close() return size end local tab = {} for i = 0, files.Count - 1 do local file = files[i] local name = CS.XFileTool.GetFileName(file) if name ~= INDEX then local asset = string.sub(file, #cdnPath + 2) local size = GetFileSize(file) table.insert(tab, "[LaunchTest] " .. tostring(i + 1) .. "、file:" .. tostring(file) .. ", name:" .. tostring(name) .. ", asset:" .. tostring(asset) .. ", size:" .. tostring(size)) DocumentIndexTable[asset] = {name, nil, size} end end if #tab > 0 then print(table.concat(tab, "\n")) end end end CompleteDownload = function() print("CompleteDownload!") CsApplication.SetProgress(1) -- 1:基础资源 2:完整资源 local downloadMode = XLaunchDlcManager.IsFullDownload(CsInfo.Version) and 2 or 1 local dict = {["type"] = ResFileType, ["version"] = NewVersion, ["size"] = UpdateSize, ["mode"] = downloadMode} DoRecord(dict, "80012", "DownloadNewFilesEnd") CS.XAppEventManager.LogAppEvent(CS.XAppEventConfig.Resource_Download_End) OnCompleteResFilesInit() end local function ClearData() ApplicationIndexTable = nil DocumentIndexTable = nil CurrentFileTable = nil DlcIndexTable = nil AllFileTableDlc = nil NeedFileSet = nil DlcNeedFileMap = nil DownloadedMap = nil end OnCompleteResFilesInit = function() if IsInGame then if not IsPause then XLaunchDlcManager.DoneDownloadInGame() end ClearData() if OnCompleteCallback then OnCompleteCallback(IsPause) end return end local urlTable = {} local hashTable = {} if IsDlcBuild then if AllFileTableDlc then for asset, info in pairs(AllFileTableDlc) do -- 未剔除包体已有资源,dlc补丁逻辑会访问路径出错 urlTable[asset] = DocumentFilePath .. "/" .. ResFileType .. "/" .. info[1] hashTable[asset] = info[1] end XLaunchDlcManager.DoneDownloadInLaunch() end else if DocumentIndexTable then for asset, info in pairs(DocumentIndexTable) do urlTable[asset] = DocumentFilePath .. "/" .. ResFileType .. "/" .. info[1] hashTable[asset] = info[1] end end end for asset, info in pairs(ApplicationIndexTable) do if not urlTable[asset] or HasLocalFiles then -- 包体资源优先于本地测试资源 urlTable[asset] = ApplicationFilePath .. "/" .. ResFileType .. "/" .. info[1] hashTable[asset] = info[1] end end ClearData() RemoveEvents() -- 完成回调 if OnCompleteCallback then OnCompleteCallback(urlTable, hashTable, NeedUpdate, HasLocalFiles) end end RemoveEvents = function() if NeedShowSelect then CsGameEventManager:RemoveEvent(CS.XEventId.EVENT_LAUNCH_DONE_DOWNLOAD_SELECT, OnNotifyEvent) end NeedShowSelect = nil -- 网络下载失败重试时,不再弹选择弹窗 end DoRecord = function(...) if IsInGame then return end CS.XRecord.Record(...) end IsFullDownloadSelectType = function() local selectType = CS.XRemoteConfig.LaunchSelectType return selectType == nil or selectType == 0 end return XLaunchFileModule end return module_creator