-- 资源更新器 --//TODO:1,可能考虑把共公部分路径抽取出来,以减少配置文件的容量;2,语言文件考虑增量更新的方式,避免改一点点更新整个文件(语言文件还是挺大的) -- 服务器 local csSelf = CLVerManager.self local baseUrl = CLVerManager.self.baseUrl --"http://gamesres.ultralisk.cn/cdn/test"; local platform = "" local newestVerPath = "newestVers" local resVer = "resVer" local versPath = "VerCtl" local fverVer = "VerCtl.ver" --本地所有版本的版本信息 ---@type System.Collections.Hashtable local localverVer = Hashtable() ---@type System.Collections.Hashtable local serververVer = Hashtable() --======================== local verPriority = "priority.ver" ---@type System.Collections.Hashtable local localPriorityVer = Hashtable() --本地优先更新资源 ---@type System.Collections.Hashtable local serverPriorityVer = Hashtable() --服务器优先更新资源 local verOthers = "other.ver" ---@type System.Collections.Hashtable local otherResVerOld = Hashtable() --所有资源的版本管理 ---@type System.Collections.Hashtable local otherResVerNew = Hashtable() --所有资源的版本管理 local tmpUpgradePirorityPath = "tmpUpgrade4Pirority" local haveUpgrade = false local is2GNetUpgrade = CLVerManager.self.is2GNetUpgrade local is3GNetUpgrade = CLVerManager.self.is3GNetUpgrade local is4GNetUpgrade = CLVerManager.self.is4GNetUpgrade local onFinishInit = nil local progressCallback = nil local mVerverPath = "" local mVerPrioriPath = "" local mVerOtherPath = "" ---@type System.Collections.Hashtable local needUpgradeVerver = Hashtable() local progress = 0 local isNeedUpgradePriority = false local needUpgradePrioritis = Queue() local isSucessUpgraded = false local verVerMD5 = "" CLLVerManager = {} -- 更新初始化 --[[ iprogressCallback: 进度回调,回调有两个参数 ifinishCallback: 完成回调 isdoUpgrade: 是否做更新处理 --]] function CLLVerManager.init(iprogressCallback, ifinishCallback, isdoUpgrade, _verVerMD5) haveUpgrade = false verVerMD5 = _verVerMD5 CLVerManager.self.haveUpgrade = false isNeedUpgradePriority = false localverVer:Clear() serververVer:Clear() localPriorityVer:Clear() serverPriorityVer:Clear() otherResVerOld:Clear() otherResVerNew:Clear() platform = CLPathCfg.self.platform CLVerManager.self.platform = platform mVerverPath = PStr.begin():a(CLPathCfg.self.basePath):a("/"):a(resVer):a("/"):a(platform):a("/"):a(fverVer):e() mVerPrioriPath = PStr.begin():a(CLPathCfg.self.basePath):a("/"):a(resVer):a("/"):a(platform):a("/"):a(versPath):a("/"):a( verPriority ):e() mVerOtherPath = PStr.begin():a(CLPathCfg.self.basePath):a("/"):a(resVer):a("/"):a(platform):a("/"):a(versPath):a("/"):a( verOthers ):e() CLVerManager.self.mVerverPath = mVerverPath CLVerManager.self.mVerPrioriPath = mVerPrioriPath CLVerManager.self.mVerOtherPath = mVerOtherPath progressCallback = iprogressCallback onFinishInit = ifinishCallback if (not isdoUpgrade) then CLLVerManager.loadPriorityVer() -- 后面会调用onFinish的回调 CLLVerManager.loadOtherResVer(true) return end --[[* /// None 无网络 /// WiFi /// 2G /// 3G /// 4G /// Unknown */ --]] local netState = Utl.getNetState() local netActived = true if (netState == "None") then netActived = false elseif (netState == "2G") then if (not is2GNetUpgrade) then netActived = false end elseif (netState == "3G") then if (not is3GNetUpgrade) then netActived = false end elseif (netState == "4G") then if (not is4GNetUpgrade) then netActived = false end elseif (netState == "WiFi") then netActived = true elseif (netState == "Unknown") then netActived = true end local canDoUpgrade = false if (platform == "Android") then if (not CLCfgBase.self.isEditMode and netActived) then canDoUpgrade = true end else if (not CLCfgBase.self.isEditMode and Utl.netIsActived()) then canDoUpgrade = true end end if (canDoUpgrade) then canDoUpgrade = CLLVerManager.checkChannel() if (canDoUpgrade) then CLLVerManager.netWorkActived() else CLLVerManager.loadPriorityVer() -- 后面会调用onFinish的回调 CLLVerManager.loadOtherResVer(true) end else -- 说明是编辑器环境 Utl.doCallback(onFinishInit, true) end end -- 验证渠道是否需要更新 function CLLVerManager.checkChannel() local defaultReuslt = false -- 先判断是否已经取得取渠道 local fpath = "channels.json" -- 得渠道控制醘数据 local content = FileEx.readNewAllText(fpath) local channels = nil if (content ~= nil) then channels = JSON.DecodeMap(content) else return defaultReuslt end -- 取得当前版本的渠道数据 fpath = "chnCfg.json" -- 该文在打包时会自动放在streamingAssetsPath目录下,详细参见打包工具 content = FileEx.readNewAllText(fpath) local chnCfg = nil if (content ~= nil) then chnCfg = JSON.DecodeMap(content) else return defaultReuslt end -- 取得当前包的渠道在渠道配置文件中是否有配置可更新 if (MapEx.getBool(channels, MapEx.getString(chnCfg, "SubChannel"))) then return true else return false end return defaultReuslt end -- 验证网络是否可用 function CLLVerManager.netWorkActived() local onCheckNetSateSuc = function(...) CLVerManager.self:StartCoroutine(FileEx.readNewAllBytesAsyn(mVerverPath, CLLVerManager.onGetlcalVerverMap)) end local onCheckNetSateFail = function(...) printw("Cannot connect Server or Net !!!") CLLVerManager.loadPriorityVer() -- 后面会调用onFinish的回调 CLLVerManager.loadOtherResVer(false) end local url = Utl.urlAddTimes(PStr.b():a(baseUrl):a("/netState.txt"):e()) WWWEx.get(url, CLAssetType.text, onCheckNetSateSuc, onCheckNetSateFail, nil, true, 2) end --[[ /// /// Ons the get verver map.取得本地版本文件的版本信息 /// /// /// Buff. /// --]] function CLLVerManager.onGetlcalVerverMap(buff) if (buff ~= nil) then localverVer = CLVerManager.self:toMap(buff) else localverVer = Hashtable() end CLLVerManager.getServerVerverMap() end --[[ /// /// Gets the server verver map.取得服务器版本文件的版本信息 /// --]] function CLLVerManager.getServerVerverMap(...) local url = "" if CLCfgBase.self.hotUpgrade4EachServer then -- 说明是每个服务器单独处理更新控制 url = PStr.begin():a(baseUrl):a("/"):a(mVerverPath):a("."):a(verVerMD5):e() else url = PStr.begin():a(baseUrl):a("/"):a(mVerverPath):e() end WWWEx.get( Utl.urlAddTimes(url), CLAssetType.bytes, CLLVerManager.onGetServerVerverBuff, CLLVerManager.onGetServerVerverBuff, nil, true, 2 ) end function CLLVerManager.onGetServerVerverBuff(content, orgs) if (content ~= nil) then serververVer = CLVerManager.self:toMap(content) else serververVer = Hashtable() end --判断哪些版本控制信息需要更新 CLLVerManager.checkVervers() end function CLLVerManager.checkVervers() progress = 0 needUpgradeVerver:Clear() isNeedUpgradePriority = false local ver = nil local keysList = MapEx.keys2List(serververVer) local count = keysList.Count local key = "" for i = 0, count - 1 do key = keysList[i] ver = MapEx.getString(localverVer, key) if (ver == nil or ver ~= MapEx.getString(serververVer, key)) then MapEx.set(needUpgradeVerver, key, false) end end keysList:Clear() keysList = nil if (needUpgradeVerver.Count > 0) then if (progressCallback ~= nil) then progressCallback(needUpgradeVerver.Count, 0) end keysList = MapEx.keys2List(needUpgradeVerver) count = keysList.Count key = "" for i = 0, count - 1 do key = keysList[i] CLLVerManager.getVerinfor(key, MapEx.getString(serververVer, key)) end keysList:Clear() keysList = nil else CLLVerManager.loadPriorityVer() CLLVerManager.loadOtherResVer(true) end end -- 取得版本文件 function CLLVerManager.getVerinfor(fPath, verVal) local url = PStr.b():a(baseUrl):a("/"):a(fPath):a("."):a(verVal):e() -- 注意是加了版本号的,可以使用cdn WWWEx.get(url, CLAssetType.bytes, CLLVerManager.onGetVerinfor, CLLVerManager.onGetVerinfor, fPath, true, 2) end function CLLVerManager.onGetVerinfor(content, orgs) if (content ~= nil) then local fPath = orgs progress = progress + 1 MapEx.set(localverVer, fPath, MapEx.getString(serververVer, fPath)) local fName = PStr.b():a(CLPathCfg.persistentDataPath):a("/"):a(newestVerPath):a("/"):a(fPath):e() if (Path.GetFileName(fName) == "priority.ver") then -- 优先更新需要把所有资源更新完后才记录 isNeedUpgradePriority = true serverPriorityVer = CLVerManager.self:toMap(content) else FileEx.CreateDirectory(Path.GetDirectoryName(fName)) File.WriteAllBytes(fName, content) end MapEx.set(needUpgradeVerver, fPath, true) if (progressCallback ~= nil) then progressCallback(needUpgradeVerver.Count, progress) end -- if (isFinishAllGet ()) then if (needUpgradeVerver.Count == progress) then if (not isNeedUpgradePriority) then -- 说明没有优先资源需要更新,可以不做其它处理了 --同步到本地 local ms = MemoryStream() B2OutputStream.writeMap(ms, localverVer) local vpath = PStr.b():a(CLPathCfg.persistentDataPath):a("/"):a(mVerverPath):e() FileEx.CreateDirectory(Path.GetDirectoryName(vpath)) File.WriteAllBytes(vpath, ms:ToArray()) CLLVerManager.loadPriorityVer() CLLVerManager.loadOtherResVer(true) else CLLVerManager.checkPriority() --处理优先资源更新 end end else CLLVerManager.initFailed() end end function CLLVerManager.checkPriority() --取得本地优先更新资源版本信息 CLVerManager.self:StartCoroutine(FileEx.readNewAllBytesAsyn(mVerPrioriPath, CLLVerManager.onGetNewPriorityMap)) end function CLLVerManager.onGetNewPriorityMap(buff) if (buff ~= nil) then localPriorityVer = CLVerManager.self:toMap(buff) else localPriorityVer = Hashtable() end CLVerManager.self.localPriorityVer = localPriorityVer -- 同步到c# progress = 0 needUpgradeVerver:Clear() needUpgradePrioritis:Clear() local ver = nil local keysList = MapEx.keys2List(serverPriorityVer) local key = nil local count = keysList.Count for i = 0, count - 1 do key = keysList[i] ver = MapEx.getString(localPriorityVer, key) if (ver == nil or ver ~= MapEx.getString(serverPriorityVer, key)) then MapEx.set(needUpgradeVerver, key, false) needUpgradePrioritis:Enqueue(key) end end keysList:Clear() keysList = nil if (needUpgradePrioritis.Count > 0) then haveUpgrade = true CLVerManager.self.haveUpgrade = true if (progressCallback ~= nil) then progressCallback(needUpgradeVerver.Count, 0) end CLLVerManager.getPriorityFiles(needUpgradePrioritis:Dequeue()) else --同步总的版本管理文件到本地 local ms = MemoryStream() B2OutputStream.writeMap(ms, localverVer) local vpath = PStr.b():a(CLPathCfg.persistentDataPath):a("/"):a(mVerverPath):e() FileEx.CreateDirectory(Path.GetDirectoryName(vpath)) File.WriteAllBytes(vpath, ms:ToArray()) CLLVerManager.loadOtherResVer(true) end end -- 取得优先更新的资源 function CLLVerManager.getPriorityFiles(fPath) local Url = "" local verVal = MapEx.getString(serverPriorityVer, fPath) Url = PStr.begin():a(baseUrl):a("/"):a(fPath):a("."):a(verVal):e() -- 把版本号拼在后面 -- print("Url==" .. Url); WWWEx.get(Url, CLAssetType.bytes, CLLVerManager.onGetPriorityFiles, CLLVerManager.initFailed, fPath, true, 2) if (progressCallback ~= nil) then progressCallback(needUpgradeVerver.Count, progress, WWWEx.getWwwByUrl(Url)) end end function CLLVerManager.onGetPriorityFiles(content, orgs) if (content == nil) then CLLVerManager.initFailed() return end local fPath = orgs progress = progress + 1 -- 先把文件放在tmp目录,等全部下载好后再移到正式目录 local fName = PStr.b():a(CLPathCfg.persistentDataPath):a("/"):a(tmpUpgradePirorityPath):a("/"):a(fPath):e() FileEx.CreateDirectory(Path.GetDirectoryName(fName)) File.WriteAllBytes(fName, content) --同步到本地 MapEx.set(localPriorityVer, fPath, MapEx.getString(serverPriorityVer, fPath)) MapEx.set(needUpgradeVerver, fPath, true) CLVerManager.self.localPriorityVer = localPriorityVer if (progressCallback ~= nil) then progressCallback(needUpgradeVerver.Count, progress) end if (needUpgradePrioritis.Count > 0) then CLLVerManager.getPriorityFiles(needUpgradePrioritis:Dequeue()) else --已经把所有资源取得完成 -- 先把文件放在tmp目录,等全部下载好后再移到正式目录 local keysList = MapEx.keys2List(needUpgradeVerver) local count = keysList.Count local key = nil local fromFile = "" local toFile = "" for i = 0, count - 1 do key = keysList[i] fromFile = PStr.b():a(CLPathCfg.persistentDataPath):a("/"):a(tmpUpgradePirorityPath):a("/"):a(key):e() toFile = PStr.begin():a(CLPathCfg.persistentDataPath):a("/"):a(key):e() FileEx.CreateDirectory(Path.GetDirectoryName(toFile)) File.Copy(fromFile, toFile, true) end Directory.Delete(PStr.b():a(CLPathCfg.persistentDataPath):a("/"):a(tmpUpgradePirorityPath):e(), true) keysList:Clear() keysList = nil --同步优先资源更新的版本管理文件到本地 local ms = MemoryStream() B2OutputStream.writeMap(ms, localPriorityVer) local vpath = PStr.b():a(CLPathCfg.persistentDataPath):a("/"):a(mVerPrioriPath):e() FileEx.CreateDirectory(Path.GetDirectoryName(vpath)) File.WriteAllBytes(vpath, ms:ToArray()) --同步总的版本管理文件到本地 ms = MemoryStream() B2OutputStream.writeMap(ms, localverVer) vpath = PStr.b():a(CLPathCfg.persistentDataPath):a("/"):a(mVerverPath):e() FileEx.CreateDirectory(Path.GetDirectoryName(vpath)) File.WriteAllBytes(vpath, ms:ToArray()) CLLVerManager.loadOtherResVer(true) end end function CLLVerManager.loadPriorityVer() CLVerManager.self:StartCoroutine(FileEx.readNewAllBytesAsyn(mVerPrioriPath, CLLVerManager.onGetVerPriority)) end function CLLVerManager.onGetVerPriority(buff) if (buff ~= nil) then localPriorityVer = CLVerManager.self:toMap(buff) else localPriorityVer = Hashtable() end CLVerManager.self.localPriorityVer = localPriorityVer end function CLLVerManager.loadOtherResVer(sucessProcUpgrade) isSucessUpgraded = sucessProcUpgrade CLVerManager.self:StartCoroutine(FileEx.readNewAllBytesAsyn(mVerOtherPath, CLLVerManager.onGetVerOther)) end function CLLVerManager.onGetVerOther(buff) if (buff ~= nil) then otherResVerOld = CLVerManager.self:toMap(buff) else otherResVerOld = Hashtable() end CLVerManager.self.otherResVerOld = otherResVerOld local path = PStr.b():a(newestVerPath):a("/"):a(mVerOtherPath):e() CLVerManager.self:StartCoroutine(FileEx.readNewAllBytesAsyn(path, CLLVerManager.onGetNewVerOthers)) end function CLLVerManager.onGetNewVerOthers(buff) if (buff ~= nil) then otherResVerNew = CLVerManager.self:toMap(buff) else otherResVerNew = Hashtable() end CLVerManager.self.otherResVerNew = otherResVerNew progressCallback = nil Utl.doCallback(onFinishInit, isSucessUpgraded) end function CLLVerManager.initFailed(...) if (progressCallback ~= nil) then progressCallback(needUpgradeVerver.Count, progress, nil) end CLLVerManager.loadPriorityVer() CLLVerManager.loadOtherResVer(false) printw("initFailed") end function CLLVerManager.isHaveUpgrade(...) return haveUpgrade end return CLLVerManager