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 UNCHECKED_FILE_EXTENSION = ".unchecked" local module_creator = function() local XLaunchFileModule = {} local MESSAGE_PACK_MODULE_NAME = "XLaunchCommon/XMessagePack" require(MESSAGE_PACK_MODULE_NAME) 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 DlcCommonIdList 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 CurrentUpdateSize = 0 -- local HasLocalFiles = false -- Local Function local CheckIndexFile local ResolveResIndex local PrepareDownload local DownloadFiles local CompleteDownload local OnCompleteResFilesInit local LoadIndexTable local LoadIndexTableWithDlcInfo local InitDocumentIndex local DownloadDlcIndexs local DoPrepareDownload local OnNotifyEvent local IsDlcBuild = false local NeedShowSelect = false 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() IsDlcBuild = CsInfo.IsDlcBuild XLaunchDlcManager.SetIsDlcBuild(IsDlcBuild) 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() NeedShowSelect = XLaunchDlcManager.NeedShowSelectDownloadPart(CsInfo.Version) and IsDlcBuild -- 每个大版本只会弹出一次选择更新,小更新沿用选择结果 end if CS.XRemoteConfig.IsHideFunc then --NeedUpdate = false end CsLog.Debug("NeedUpdate:"..tostring(NeedUpdate)..",type:"..ResFileType) -- CheckIndexFile() end -- function XLaunchFileModule.GetOffset() -- return OFFSET -- end DownloadDlcIndexs = function(cb) if not IsDlcBuild then cb() return end DocumentIndexTable, DlcIndexTable, DlcCommonIdList = LoadIndexTableWithDlcInfo(DocumentIndexPath) 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) 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 str = string.format("%s/%s/%s/%s", DocumentUrl, NewVersion, ResFileType, name) local str2 = DocumentFilePath .. "/" .. ResFileType .. "/" .. name local downloader = CS.XUriPrefixDownloader(str, str2, cache, sha1, TIMEOUT, RETRY, READ_TIMEOUT) local size = 0 --CsLog.Debug("DocumentUrl:"..DocumentUrl) --CsLog.Debug("str:"..str) --CsLog.Debug("str2:"..str2) 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 CS.XRecord.Record(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 and CS.XFileTool.CheckSha1(documentFilePath, sha1) then CsLog.Debug("[Download] HasUpdated:" .. tostring(HasUpdated)) ResolveResIndex() return 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 DownloadDlcIndexs(function() AppVersionModule.UpdateDocVersion() ResolveResIndex() end) end end end) end LoadIndexTable = 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] 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 {} local dlcCommonIdList = indexFile[3] or {} assetBundle:Unload(true) return indexTable, dlcIndexTable, dlcCommonIdList end return nil end -- 解析doc目录下index InitDocumentIndex = function() 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, DlcCommonIdList = LoadIndexTableWithDlcInfo(DocumentIndexPath) else DocumentIndexTable = LoadIndexTable(DocumentIndexPath) -- {[assetPath] = value{[1] = Name, [2] = Sha1, [3] = Size}, ... } end end CurrentFileTable = {} -- 当前需下载资源 AllFileTableDlc = {} -- DLC完整资源 local count = 0 NeedFileSet = {} -- 需下载标记 -- 基础补丁 for asset, info in pairs(DocumentIndexTable) do NeedFileSet[info[1]] = true CurrentFileTable[asset] = info AllFileTableDlc[asset] = info end -- 统计资源 if IsDlcBuild then XLaunchDlcManager.Init(DlcIndexTable, DlcCommonIdList) -- 分包补丁 for dlcId, dlcIndexInfo in pairs(DlcIndexTable) do local dlcIndexPath = DocumentIndexDir .. dlcIndexInfo[1] local dlcTable = LoadIndexTable(dlcIndexPath) XLaunchDlcManager.SetDlcIndexInfo(dlcId, dlcTable) -- 历史选择的分包下载记录(不弹出选择框是用于默认下载) local hasDownloadDlc = (not NeedShowSelect) and XLaunchDlcManager.HasStartDownloadDlc(dlcId) CsLog.Debug("[DLC] dlcId: ".. tostring(dlcId) .. ", hasDownloadDlc: " .. tostring(hasDownloadDlc) .. ", NeedShowSelect:" .. tostring(NeedShowSelect)) for asset, info in pairs(dlcTable) do NeedFileSet[info[1]] = true if hasDownloadDlc then CurrentFileTable[asset] = info end AllFileTableDlc[asset] = info end end -- 剔除包内已有资源(需asset与Name都对应) for asset, info in pairs(ApplicationIndexTable) do local value = AllFileTableDlc[asset] if value and value[1] == info[1] then AllFileTableDlc[asset] = nil CurrentFileTable[asset] = nil count = count + 1 end end else CurrentFileTable = DocumentIndexTable -- 剔除包内已有资源(需asset与Name都对应) for asset, info in pairs(ApplicationIndexTable) do local value = CurrentFileTable[asset] if value and value[1] == info[1] then CurrentFileTable[asset] = nil count = count + 1 end end end CsLog.Debug("[Download] 包内已有资源数量:" .. count) end ResolveResIndex = function() CS.XAppEventManager.LogAppEvent(CS.XAppEventConfig.Version_Checking_End) local applicationIndexPath = ApplicationFilePath .. "/" .. ResFileType .. "/" .. INDEX 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] CS.XRecord.Record(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 NeedShowSelect then for _, info in pairs(AllFileTableDlc) do AllUpdateTable[info[1]] = info AllUpdateTableCount = AllUpdateTableCount + 1 AllUpdateSize = AllUpdateSize + info[3] end end CsLog.Debug("[Download] IsDlcBuild:" .. tostring(IsDlcBuild)) CsLog.Debug(string.format("[Download] UpdateSize: %d, UpdateTableCount: %d, AllUpdateSize: %d, AllUpdateTableCount: %d", UpdateSize, UpdateTableCount, AllUpdateSize, AllUpdateTableCount)) -- 2166 -- 基础包补丁 local deleteKey = SPECIAL_DELETE_MATRIX_PREF_KEY .. tostring(AppVersionModule.GetAppVersion()) local isMatrix = ResFileType == "matrix" 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 = CS.XFileTool.GetFiles(DocumentFilePath .. "/" .. ResFileType) local lastVerCount = 0 local otherCount = 0 local totalCount = 0 --是否启用IOS后台下载 --在启用时,由于IOS校验流程的统一需要,因此文件下载完可能还未校验,需要假设资源是完整的 --在以上条件下,需要合理估计仍然需要下载的文件大小,因此需要减去对仅未验证的文件的大小 local isUseIosDownloadService = (CS.XRemoteConfig.DownloadMethod == 0) and AppPathModule.IsIos() for i = 0, files.Length - 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 not NeedFileSet[name] then CsLog.Debug("[Download] 清理上一版本资源" .. tostring(name) .. ", need:" .. tostring((not NeedFileSet[name]))) 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 NeedShowSelect then local infoDlc = AllUpdateTable[name] if infoDlc then AllUpdateTable[name] = nil AllUpdateTableCount = AllUpdateTableCount - 1 AllUpdateSize = AllUpdateSize - infoDlc[3] 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 CS.XFileTool.DeleteFile(file) :: CONTINUE :: end CsLog.Debug(string.format("[Download] 资源清理 本地总数:%d, 清理上版本数:%d, 其他清理:%d, 需更新: %d, dlc需更新:%d", totalCount, lastVerCount, otherCount, UpdateTableCount, AllUpdateTableCount)) if checkClean then CsLog.Debug("[Download] 清理上一版本资源完成。") CS.UnityEngine.PlayerPrefs.SetInt(deleteKey, 1) CS.UnityEngine.PlayerPrefs.Save() end PrepareDownload() 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 OnDoneSelect = function(isFullDownload) DlcManager.DoneSelectDownloadPart(CsInfo.Version) if isFullDownload then DlcManager.SetAllNeedDownload() UpdateTable = AllUpdateTable end DoPrepareDownload() end PrepareDownload = function() if UpdateTableCount <= 0 and (not NeedShowSelect or AllUpdateTableCount <=0) then OnCompleteResFilesInit() return end --todo 如果是dlc打包,显示选择框,选择完重新下载 if NeedShowSelect then CsGameEventManager:RegisterEvent(CS.XEventId.EVENT_LAUNCH_DONE_DOWNLOAD_SELECT, function(evt,data) OnDoneSelect(data[0]) end) CsGameEventManager:Notify(CS.XEventId.EVENT_LAUNCH_SHOW_DOWNLOAD_SELECT,UpdateSize,AllUpdateSize) else DoPrepareDownload() end end DoPrepareDownload = function() local dict = {["type"] = ResFileType, ["version"] = NewVersion} CS.XRecord.Record(dict, "80011", "StartDownloadNewFiles") local unit,num = GetSizeAndUnit(UpdateSize) -- 日服不做热更时网络状态判断 --if (UnityApplication.internetReachability == CS.UnityEngine.NetworkReachability.ReachableViaCarrierDataNetwork and UpdateSize > SIZE) then --BDC -- CS.XHeroBdcAgent.BdcUpdateGame("203", "1", "0") -- local tmpStr = string.format("%0.2f%s%s", num, unit, CsApplication.GetText("UpdateCheck")) -- CsTool.WaitCoroutine(CsApplication.CoDialog(CsApplication.GetText("Tip"), tmpStr, CsApplication.Exit, function() -- DownloadFiles() -- end)) -- return --end --BDC CS.XHeroBdcAgent.BdcUpdateGame("203", "1", "0") local tmpStr = string.format("%s%0.2f %s", CsApplication.GetText("UpdateCheck"), num, unit) -- 海外调整热更文本 -- #104203 文本最后与单位新增一个空格 CsTool.WaitCoroutine(CsApplication.CoDialog(CsApplication.GetText("Tip"), tmpStr, CsApplication.Exit, function() DownloadFiles() end)) return 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 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 OnProgressCallback then 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() 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 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 then CsApplication.SetProgress(progress) end if OnProgressCallback then OnProgressCallback(progress) end elseif manager.StateInt == IosDownloadState.Verifying then CS.XGameEventManager.Instance:Notify(CS.XEventId.EVENT_LAUNCH_START_LOADING) CsApplication.SetMessage(string.format("正在校验中(%d/%d)", verifier.CurrentCheckCount, verifier.TotalNeedCheckCount)) 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() local updateFileText = CsApplication.GetText("UpdateFile") local iter, t, key = pairs(UpdateTable) local info local iterKey = nil local Loop Loop = function() key, info = iter(t, iterKey) if not key then CompleteDownload() return end local name = info[1] local sha1 = info[2] -- 补丁index中记录的sha1,和下载后文件sha1对比 CsApplication.SetMessage(updateFileText .. ": " .. name) local str = string.format("%s/%s/%s/%s", DocumentUrl, NewVersion, ResFileType, name) local str2 = DocumentFilePath .. "/" .. ResFileType .. "/" .. name local downloader = CS.XUriPrefixDownloader(str, str2, true, sha1, TIMEOUT, RETRY, READ_TIMEOUT) local size = 0 CsTool.WaitCoroutinePerFrame(downloader:Send(), function(isComplete) if not isComplete then -- CurrentUpdateSize = CurrentUpdateSize - size + downloader.CurrentSize size = downloader.CurrentSize local updateProgress = UpdateSize == 0 and 0 or CurrentUpdateSize / UpdateSize CsApplication.SetProgress(updateProgress) if OnProgressCallback then OnProgressCallback(updateProgress) end else if downloader.State ~= CS.XDownloaderState.Success then local msg = "[Download] error, state error, state: " .. tostring(downloader.State) CsLog.Error(msg) local dict = {} dict.file_name = name dict.file_size = info[3] CS.XRecord.Record(dict, "80007", "XFileManagerDownloadError") local exitCb = OnExitCallback or CsApplication.Exit ShowStartErrorDialog("FileManagerInitFileTableDownloadError",exitCb, function() Loop() end, CsApplication.GetText("Retry")) -- 重试 return end CurrentUpdateSize = CurrentUpdateSize - size + downloader.Size iterKey = key Loop() end end) end Loop() end DownloadFiles = function() CsGameEventManager:Notify(CS.XEventId.EVENT_LAUNCH_START_DOWNLOAD, UpdateSize) CS.XAppEventManager.LogAppEvent(CS.XAppEventConfig.Resource_Download_Start) 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() if isUseAndroidDownloadService and ResFileType == RES_FILE_TYPE.MATRIX_FILE then CsLog.Debug("安卓后台下载模式") AndroidBackgroundDownload() elseif isUseIosDownloadService and ResFileType == RES_FILE_TYPE.MATRIX_FILE then CsLog.Debug("IOS后台下载模式") IosBackgroundDownload() else CsLog.Debug("传统下载模式") TraditionalDownload() end end CompleteDownload = function() CsApplication.SetProgress(1) local dict = {["type"] = ResFileType, ["version"] = NewVersion} CS.XRecord.Record(dict, "80012", "DownloadNewFilesEnd") CS.XAppEventManager.LogAppEvent(CS.XAppEventConfig.Resource_Download_End) OnCompleteResFilesInit() end OnCompleteResFilesInit = function() local urlTable = {} if IsDlcBuild then if AllFileTableDlc then for asset, info in pairs(AllFileTableDlc) do urlTable[asset] = DocumentFilePath .. "/" .. ResFileType .. "/" .. info[1] end XLaunchDlcManager.DoneDownload() end else if DocumentIndexTable then for asset, info in pairs(DocumentIndexTable) do urlTable[asset] = DocumentFilePath .. "/" .. ResFileType .. "/" .. 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] end end ApplicationIndexTable = nil DocumentIndexTable = nil CurrentFileTable = nil DlcIndexTable = nil AllFileTableDlc = nil if NeedShowSelect then CsGameEventManager:RemoveEvent(CS.XEventId.EVENT_LAUNCH_DONE_DOWNLOAD_SELECT, OnNotifyEvent) XLaunchDlcManager.DoneSelectDownloadPart(CsInfo.Version) -- 下载完成后才记录选择记录 end -- 完成回调 if OnCompleteCallback then OnCompleteCallback(urlTable, NeedUpdate, HasLocalFiles) end end return XLaunchFileModule end return module_creator