--[[ 管理所有子游戏的版本信息,更新状态,及更新子游戏 负责下载所有子游戏的游戏图标,并将图标时间记录下来 从SubGameVersionManager获取子游戏最新的版本信息 从本地文件中获取子游戏当前的版本信息 判断子游戏是否需要更新 提供子游戏更新的接口 子游戏列表及当前版本号存本地文件, subGameList = { [gameId] = "1022", [gameId] = "1022", } --]] local SubGameVersionManager = class("SubGameVersionManager") function SubGameVersionManager:ctor() cc.GameObject.extend(self) self:addComponent(require("luaScript.cc.components.behavior.EventProtocol"):new()):exportMethods() -- 是否测试下载 self.isTestUpdate = false -- 子游戏列表 self.subGameList = {} -- 本地记录的文件信息 self.GameVersionsKey = "GameVersions"; self.GameVersions = {} -- self.GameVersions[3] = 10000; -- self.GameVersions[6] = 1000; --基础包 --self.GameVersions[1001] = -1; --self.GameVersions[1002] = -1; --self.GameVersions[1003] = -1; -- 从本地读取已经安装的子游戏列表 -- 以及每个子游戏的当前版本号 self:loadVersionsFromFile() --处理一下基础包的版本号 self.GameVersions[1001] = self.GameVersions[1001]==1000 and -1 or self.GameVersions[1001] self.GameVersions[1002] = self.GameVersions[1002]==1000 and -1 or self.GameVersions[1002] self.GameVersions[1003] = self.GameVersions[1003]==1000 and -1 or self.GameVersions[1003] -- self.GameVersions[3] = self.GameVersions[3]==10000 and -1 or self.GameVersions[3] -- 子游戏下载器 self.updaterList = {} --排序 self.info = {}; -- self:loadFromFile(); end -- 获取子游戏的版本 -- 如果指定的游戏没有安装,则返回-1 function SubGameVersionManager:getSubGameVersionNum(gameId) gameId = tonumber(gameId) if self.GameVersions[gameId] then return self.GameVersions[gameId] else return -1 end end -- 从本地读取游戏版本信息 function SubGameVersionManager:loadVersionsFromFile() local locString = loadUserInfo(self.GameVersionsKey) if not locString or locString == "" then return end logD("SubGameVersionManager:loadVersionsFromFile() locString = ", locString) local locData = json.decode(locString) if locData then for k,v in pairs(locData) do self.GameVersions[tonumber(k)] = tonumber(v) end else logD("SubGameVersionManager:loadVersionsFromFile() locString:"..locString) end end -- 将游戏版本信息写入到本地 function SubGameVersionManager:saveVersionsToFile() local locString = json.encode(self.GameVersions) logD("SubGameVersionManager:saveVersionsToFile() locString = ", locString) saveUserInfo(self.GameVersionsKey, locString) end -- 保存子游戏的资源版本号 function SubGameVersionManager:saveSubGameVersion(gameId, newVersion) if not self.GameVersions then self.GameVersions = {} end self.GameVersions[tonumber(gameId)] = newVersion self:saveVersionsToFile() end -- 子游戏是否已安装 function SubGameVersionManager:isInstaller(gameId) gameId = tonumber(gameId) -- WIN32且未开启测试,则默认已安装 if isWin32Platform() and self.isTestUpdate == false then return true end if (gameId and self.GameVersions and self.GameVersions[gameId]) then return true else return false end end -- 子游戏是否需要更新 function SubGameVersionManager:isNeedUpdate(gameId) logD("SubGameVersionManager:isNeedUpdate()", gameId) -- WIN32且未开启测试,则默认不需要更新 if isWin32Platform() and self.isTestUpdate == false then return false end -- 检查该游戏的基础包 local subGameConfig = getSubGameConfig(gameId) if subGameConfig and subGameConfig.fremworkId then if self:isNeedUpdate(subGameConfig.fremworkId) then return true end end local verLocal = self:getSubGameVersionNum(gameId) local verServer = app.serverConfigs:getSubGameVersionNum(gameId) logD(string.format("SubGameVersionManager:isNeedUpdate() gameId = %s, verLocal = %s, verServer = %s", gameId, verLocal, verServer)) -- 如果本地没有安装,肯定是需要更新的 if tonumber(verLocal) == -1 then logD(string.format("SubGameVersionManager:isNeedUpdate() gameId = %s, verLocal = %s", gameId, verLocal)) return true end -- 无需更新的情况 if tonumber(verServer) == 0 or tonumber(verLocal) == tonumber(verServer) then logD("SubGameVersionManager:isNeedUpdate() 无需更新") return false end -- 正常更新 if tonumber(verLocal) < tonumber(verServer) then logD("SubGameVersionManager:isNeedUpdate() 正常更新") return true end -- 版本回退 if tonumber(verLocal) > tonumber(verServer) then logD("SubGameVersionManager:isNeedUpdate() 版本回退") local writablePath = cc.FileUtils:getInstance():getWritablePath() local rootName = nil local subGameConfig = getSubGameConfig(gameId) if subGameConfig then rootName = subGameConfig.rootName elseif FRAMEWORK_DIR[gameId] then rootName = FRAMEWORK_DIR[gameId] end logD("SubGameVersionManager:isNeedUpdate() rootName = ", tostring(rootName)) if rootName then local subGameResPath = writablePath .. RomSetting.Platform .. "/" .. rootName .. "/" logD("SubGameVersionManager:isNeedUpdate() subGameResPath = ", subGameResPath) cc.FileUtils:getInstance():removeDirectory(subGameResPath) cc.FileUtils:getInstance():purgeCachedEntries() self:saveSubGameVersion(gameId, nil) end return true end -- 能走到这里来肯定是有问题的 error("SubGameVersionManager:isNeedUpdate()") return false end -- 判断某个游戏是否正在更新中 function SubGameVersionManager:isUpdating(gameId) return self.updaterList[tonumber(gameId)] ~= nil end --- -- 获取更新任务,包含子游戏及子游戏依赖的框架,可能有多重嵌套依赖 -- @param {number} gameId 子游戏id -- @return {table} 下载任务 {{gameId = 123, isUpdated = false}, {...}} -- -- function SubGameVersionManager:getSubGameUpdateTasks (gameId) if not gameId then logE("SubGameVersionManager:getSubGameUpdateTasks", "参数gameId不能为空!") return 0 end local gameVersionInfo = app.serverConfigs:getSubGameVersionInfo(gameId) if not gameVersionInfo then -- 子游戏配置信息不存在,返回0,不下载 return 0 end local updateTasks = { {gameId = gameId, isUpdated = false}, } local subGameConfig=getSubGameConfig(gameId) while (subGameConfig and subGameConfig.fremworkId and subGameConfig.fremworkId > 0) do local isNeedUpdate = self:isNeedUpdate(subGameConfig.fremworkId) if isNeedUpdate then table.insert(updateTasks, 1, {gameId = subGameConfig.fremworkId, isUpdated = false}) end subGameConfig = getSubGameConfig(subGameConfig.fremworkId) end return updateTasks; end --- -- 更新子游戏 -- @param gameId 子游戏id -- @param percentCallback 百分比回调函数 -- @param finishCallBack 下载完成回调函数 -- @return -- function SubGameVersionManager:updateSubGame(gameId, percentCallback, finishCallBack) logD("SubGameVersionManager:updateSubGame()", gameId) local gameVersionInfo = app.serverConfigs:getSubGameVersionInfo(gameId) if not gameVersionInfo then -- 如果游戏配置不存在,直接返回 logD("游戏配置不存在,不进行更新操作!") if finishCallBack then finishCallBack(); end return end self.subGameUpdateTasks = self:getSubGameUpdateTasks(gameId) -- 需要更新的任务 self.subGameTaskCount = table.nums(self.subGameUpdateTasks) -- 需要更新的任务总数 self.curSubGameUpdateIndex = 1 -- 当前第几个任务 if self.subGameTaskCount == 0 then logD("SubGameVersionManager:updateSubGame", "没有可更新的子游戏") return end -- 开始执行子游戏更新 logD("SubGameVersionManager:updateSubGame", "开始执行子游戏更新", table.tostring(self.subGameUpdateTasks)) self:startUpdateSubGame(percentCallback, finishCallBack) end --- -- 开始执行子游戏更新 -- @param percentCallback 百分比回调函数 -- @param finishCallBack 下载完成回调函数 -- @return -- function SubGameVersionManager:startUpdateSubGame(percentCallback, finishCallBack) logD("SubGameVersionManager:startUpdateSubGame()") if table.nums(self.subGameUpdateTasks) == 0 then logD("SubGameVersionManager:startUpdateSubGame", "所有子游戏下载完成!") -- 所有任务下载完成,强制显示100% if percentCallback then percentCallback(100) end -- 所有任务下载完成,执行下载完成回调 if finishCallBack then finishCallBack() end return end local task = table.remove(self.subGameUpdateTasks, 1) logD("SubGameVersionManager:startUpdateSubGame", "开始下载子游戏,gameId:", task.gameId) if self:isNeedUpdate(task.gameId) then self:updateGame(task.gameId, function (num) -- 更新下载进度,多个任务下载时,根据当前任务索引,加上之前的下载进度 percentCallback((self.curSubGameUpdateIndex - 1) / self.subGameTaskCount * 100 + num / self.subGameTaskCount) end, function () self.curSubGameUpdateIndex = self.curSubGameUpdateIndex + 1 self:startUpdateSubGame(percentCallback, finishCallBack) end) else self:startUpdateSubGame(percentCallback, finishCallBack); end end function SubGameVersionManager:updateGame(gameId, percentCallback, finishCallBack) logD("SubGameVersionManager:updateGame", "curSubGameUpdateIndex", self.curSubGameUpdateIndex) logD("SubGameVersionManager:updateGame()", gameId) local gameVersionInfo = app.serverConfigs:getSubGameVersionInfo(gameId) gameVersionInfo.gameId = gameId --框架ID添加 if gameId > 1000 then gameVersionInfo.show = false end dump(gameVersionInfo) local function onFinishCallback(newVersion) logD("SubGameVersionManager:updateSubGame() onFinishCallback()", gameId, newVersion) -- 修改数据 self:saveSubGameVersion(gameId, newVersion) --上报游戏版本 app.php:requestReportGameVer(gameId, newVersion) -- 删除下载器 self.updaterList[gameId] = nil -- 触发回调 if finishCallBack then logD("SubGameVersionManager:updateSubGame() onFinishCallback() call finishCallBack") finishCallBack(newVersion) else logD("SubGameVersionManager:updateSubGame() onFinishCallback() finishCallBack is nil") end end local updater = import("luaScript.SubGame.SubGameUpdater"):new(gameVersionInfo, percentCallback, onFinishCallback) if updater then -- 保存下载器 self.updaterList[gameId] = updater -- 开始下载 updater:start(); end end -- 更换回调函数 function SubGameVersionManager:updateCallback(gameId, percentCallback, finishCallBack) local updater = self.updaterList[gameId] if updater then local function onFinishCallback(newVersion) logD("SubGameVersionManager:updateCallback() onFinishCallback()", gameId, newVersion) -- 修改数据 self:saveSubGameVersion(gameId, newVersion) -- 删除下载器 self.updaterList[gameId] = nil -- 触发回调 if finishCallBack then logD("SubGameVersionManager:updateCallback() onFinishCallback() call finishCallBack") finishCallBack(newVersion) else logD("SubGameVersionManager:updateCallback() onFinishCallback() finishCallBack is nil") end end updater:updateCallback(percentCallback, onFinishCallback) end end -- 获取已安装的游戏列表 function SubGameVersionManager:getGameListInstalled() local listIds -- 这里不能遍历服务器配置中的列表 -- 因为如果某个子游戏隐藏了,机器人开的房间要能进去 for k,v in pairs(GAME_IDS) do if self:isInstaller(v) then if not listIds then listIds = tostring(v) else listIds = listIds .. "," .. tostring(v) end end end return listIds; end -- local fileName = "gameUserTime.data" -- function SubGameVersionManager:loadFromFile() -- local jsonString = loadStringFromFile(fileName) -- if jsonString then -- self.info = json.decode(jsonString) or {} -- end -- end -- -- 保存信息到本地文件 -- function SubGameVersionManager:saveToFile(gameId) -- local time = os.time() -- self.info[tostring(gameId)] = time -- local jsonString = json.encode(self.info) -- saveStringToFile(jsonString, fileName) -- end function SubGameVersionManager:clearGame(gameId, endCallback) local rootName = nil local gameConfig = getSubGameConfig(gameId) if gameConfig and gameConfig.rootName then rootName = gameConfig.rootName end if FRAMEWORK_DIR[gameId] then rootName = FRAMEWORK_DIR[gameId] end if rootName then local writablePath = cc.FileUtils:getInstance():getWritablePath() if gameConfig and gameConfig.resDirs then for k,v in pairs(gameConfig.resDirs) do local dir = writablePath..app.config.RomSetting.Platform.."/"..v.."/"; logD("SubGameVersionManager:clearGame() removeDirectory, dir = ", dir); cc.FileUtils:getInstance():removeDirectory(dir) end else local dir = writablePath..app.config.RomSetting.Platform.."/"..rootName.."/"; logD("SubGameVersionManager:clearGame() removeDirectory, dir = ", dir); cc.FileUtils:getInstance():removeDirectory(dir) end self.GameVersions[gameId]=nil self:saveVersionsToFile() end app.serverConfigs:requestGetSubGameVersions(endCallback) end function SubGameVersionManager:checkSubGameFiles(gameId) logD("SubGameVersionManager:checkSubGameFiles() gameId = " .. gameId); if isWin32Platform() then return true end local rootName = nil local gameConfig = getSubGameConfig(gameId) if gameConfig and gameConfig.rootName then rootName = gameConfig.rootName end if FRAMEWORK_DIR[gameId] then rootName = FRAMEWORK_DIR[gameId] end if not rootName then return true, gameId, {} end local writablePath = cc.FileUtils:getInstance():getWritablePath() local filesfile = app.config.RomSetting.Platform .. "/" .. rootName .. "/" .. "files.txt"; logD("SubGameVersionManager:checkSubGameFiles() filesfile = ", filesfile); local result, missingfiles = checkFilesExist(filesfile) return result, gameId, missingfiles; end -- 检查子游戏文件的完整性 function SubGameVersionManager:checkGameFiles(gameId) logD("SubGameVersionManager:checkGameFiles() gameId = ", gameId); local result, subGameId, missingfiles = self:checkSubGameFiles(gameId) if not result then return result, subGameId, missingfiles end local gameConfig = getSubGameConfig(gameId) if gameConfig and gameConfig.fremworkId then logD("SubGameVersionManager:checkGameFiles() fremworkId = ", gameConfig.fremworkId); local result, subGameId, missingfiles = self:checkSubGameFiles(gameConfig.fremworkId) if not result then return result, subGameId, missingfiles end end return true, gameId, {}; end return SubGameVersionManager