local lfs = lfs or require("lfs") local writablePath = cc.FileUtils:getInstance():getWritablePath(); local targetPlatform = cc.Application:getInstance():getTargetPlatform() RomSetting = loadRomSettingScript(); PhpSetting = {} -- 将废弃 function log(...) print(...) end -- 打印一般信息,开发时查看数据用 function logI(...) if target_platform ~= 0 then return end print(...) end -- 打印较重要的调试信息 function logD(...) print(...) end -- 打印错误信息 function logE(...) print(...) end -- 将废弃 function printDebug(...) print(...) end function handler(target, method) assert(method); return function(...) return method(target, ...) end end -- 从本地读取审核状态 function loadIsReview() local appPackageName = tostring(getAppPackageName()) local appVersionName = tostring(getAppVersionName()) logD("loadIsReview() appVersionName = ", appVersionName) logD("loadIsReview() appPackageName = ", appPackageName) if appPackageName == "com.dangdang.chuannan" and appVersionName == "3.0.0" then return false end if appPackageName == "com.cdhklu.yoihtts" and appVersionName == "1.0.3" then return false end local isReview = false -- 如果是配置了小游戏,则默认审核,否则默认非审核 if RomSetting and RomSetting.IosReviewType and RomSetting.IosReviewType ~= 1 then isReview = cc.UserDefault:getInstance():getBoolForKey("isReview", true); else isReview = cc.UserDefault:getInstance():getBoolForKey("isReview", false); end logD("loadIsReview() isReview = ", tostring(isReview)) return isReview; end -- 保存审核状态到本地 function saveIsReview(isReview) logD("saveIsReview() isReview = ", tostring(isReview)) cc.UserDefault:getInstance():setBoolForKey("isReview", isReview); end -- 是否开发模式 function isDevMode() return RomSetting.isDevMode == true; end function isDebug() return isDevMode(); end -- 是否软著版本 function isRuanZhu() return (RomSetting.isRuanZhu == true) end function getAppId() if RomSetting.AppId then return RomSetting.AppId; else return 0; end end function getChannelId() if RomSetting.ChannelId then return RomSetting.ChannelId; else return 100; end end -- 是否是Android操作系统 function isAndroidPlatform() local targetPlatform = cc.Application:getInstance():getTargetPlatform(); -- Android版本 if targetPlatform == 3 then return true; else return false; end end -- 是否是苹果操作系统 function isIOSPlatform() local targetPlatform = cc.Application:getInstance():getTargetPlatform(); -- 苹果版本 if (targetPlatform == 4 or targetPlatform == 5) then return true; else return false; end end function isWin32Platform() local targetPlatform = cc.Application:getInstance():getTargetPlatform(); if (targetPlatform == 0) then return true; else return false; end end -- 是否是正在审核的版本 function isReviewVersion() logD("PreloadTools::isReviewVersion()") if RomSetting and RomSetting.isReviewVersion == true then return true end local isReview = loadIsReview() logD("PreloadTools::isReviewVersion() isReview = ", tostring(isReview)) return isReview end -- 是否是苹果正在审核的版本 function isIOSReviewVersion() return isIOSPlatform() and isReviewVersion() end -- 是否正在使用小游戏审核 function isReviewWithMiniGame() if isReviewVersion() then return tonumber(RomSetting.IosReviewType) ~= 1 else return false end end -- 是否使用竖屏提交苹果审核 function isReviewByPortrait() if isReviewVersion() then return tonumber(RomSetting.IosReviewType) == 3 else return false end end function getMiniGameConfig() if RomSetting and RomSetting.IosReviewType == 3 and RomSetting.MiniGameId ~= nil then local configs = require("preload.MiniGameConfigs") if configs then return configs[RomSetting.MiniGameId] end end return nil end function getMiniGameMainViewScript() local miniGameConfig = getMiniGameConfig() if miniGameConfig then return miniGameConfig.MainViewScript else return nil end end function getMiniGameAutoUpdateViewUI() local miniGameConfig = getMiniGameConfig() if miniGameConfig then return miniGameConfig.AutoUpdateViewUI else return nil end end function loadVersionFromLua() local versionInfo = require("romFiles.version"); if versionInfo then return versionInfo.ResourceVersion else return nil end end function loadVersionFromJson() local fileName = "romFiles/version.json"; local fileString = cc.FileUtils:getInstance():getStringFromFile(fileName) return fileString or "1000" end function loadVersion() local resversionLua = loadVersionFromLua() local resVersionJson = loadVersionFromJson() local resVersion = resversionLua or resVersionJson return resVersion end -- 所有子UI都根据名字保存到这里 function getUIItems(ui) local items = {} local function onNode(node) local name = node:getName(); if type(name) == "string" then items[name] = node; end local desc = node:getDescription(); if desc == "Button" then node:setClickSoundFile(""); end return true; end -- 遍历所有子节点,把子UI取出来统一放在Items里 ui:visitNode(onNode); return items; end loadUIText = nil tipLoadUIBg = nil -- 载入UI文件,并返回UI的根节点 function loadUI(fileName) logD("loadUI() ", fileName) if false and isWin32Platform() then local info = debug.traceback() local list = string.split(info,"\"") local nameList = string.split(list[4],".") local tt = {} for k,v in ipairs(nameList) do if v ~= "" then table.insert(tt,v) end end local fList = string.split(fileName,"/") fList = string.split(fList[#fList],"."); local seq = cc.Sequence:create(cc.FadeIn:create(0.5),cc.DelayTime:create(3.0),cc.FadeOut:create(0.1)) local function createLabel() tipLoadUIBg = cc.ImageView:create() tipLoadUIBg:loadTexture("res/ui/zy_tongyong/tongyong_loading_bg.png") tipLoadUIBg:setAutoSize(false) tipLoadUIBg:setSize(cc.size(1280,100)) app.dialogLayout:addChild(tipLoadUIBg,99999) tipLoadUIBg:setPosition(cc.p(getWinSize().width/2,50)) app.dialogLayout.tipLoadUIBg = tipLoadUIBg tipLoadUIBg:setVisible(false) loadUIText = cc.Text:create(); local ttfConfig = {} ttfConfig.fontFilePath = "res/default/msyh.ttc" ttfConfig.fontSize = 35 ttfConfig.glyphs = cc.GLYPHCOLLECTION_DYNAMIC ttfConfig.customGlyphs = nil ttfConfig.distanceFieldEnabled = false ttfConfig.outlineSize = 2 ttfConfig.effectColor = cc.c4b(255,255,255,255) ttfConfig.texColor = cc.c4b(255,39,240,255) loadUIText:setFontConfig(ttfConfig); tipLoadUIBg:addChild(loadUIText) loadUIText:setPosition(cc.p(tipLoadUIBg:getSize().width/2,tipLoadUIBg:getSize().height/2)) tipLoadUIBg:runAction(seq) end if fileName ~= "res/ui/ui_common/ModelDialog.ui" and fileName ~= "res/ui/ui_tongyong/texttips.ui" then if app.dialogLayout and not app.dialogLayout.tipLoadUIBg or tolua.isnull(tipLoadUIBg)then createLabel() elseif app.dialogLayout and app.dialogLayout.tipLoadUIBg then if not tolua.isnull(tipLoadUIBg) then if fileName ~= "res/ui/ui_tongyong/duanxinchonglian.ui" then loadUIText:setText("所用UI:"..fList[1] .." 类名:".. tostring(tt[#tt])); tipLoadUIBg:stopAllActions() tipLoadUIBg:setOpacity(0) tipLoadUIBg:runAction(seq) tipLoadUIBg:setVisible(true) end end end end end local ui = cc.StreamObject:loadFromFile(fileName); ui.Items = getUIItems(ui); ui:setCollectAnimationClip(false); return ui; end -- 获得一个文件在可写文件目录中的位置 function getWritableFullName(fileName) return writablePath .. fileName; end -- 可写文件目录中的文件是否存在 function isWritableFileExist(fileName) return cc.FileSystem:fileExists(writablePath .. fileName); end -- 从可写文件目录读取一个文件的原始数据 function getWritableFileData(fileName) local targetPath = writablePath .. fileName; local f = io.open(targetPath , "rb"); if f then local data = f:read("*a"); f:close(); return data; else return nil; end end -- ROM中的文件是否存在 function isRomFileExist(fileName) local isExist = cc.FileSystem:fileExists(fileName); return isExist; end -- 从ROM读取原始文件数据 function getRomFileData(fileName) return cc.FileSystem:readData(fileName); end -- 判断某个文件是否存在 function isFileExist(fileName) return isWritableFileExist(fileName) or isRomFileExist(fileName); end function isLuaFuleExist(fileName) return cc.FileUtils:getInstance():isFileExist( fileName .. ".luac") or cc.FileUtils:getInstance():isFileExist( fileName .. ".lua") end -- 获取文件内容 function getFileData(fileName) if isWritableFileExist(fileName) then return getWritableFileData(fileName) elseif isRomFileExist(fileName) then return getRomFileData(fileName) else return nil end end -- 把一个字符串分割成数组 function split(szFullString, szSeparator) local nFindStartIndex = 1 local nSplitIndex = 1 local nSplitArray = {} while true do local nFindLastIndex, endIndex= string.find(szFullString, szSeparator, nFindStartIndex) if not nFindLastIndex then nSplitArray[nSplitIndex] = string.sub(szFullString, nFindStartIndex, string.len(szFullString)) break end nSplitArray[nSplitIndex] = string.sub(szFullString, nFindStartIndex, nFindLastIndex - 1) nFindStartIndex = endIndex + 1; nSplitIndex = nSplitIndex + 1 end return nSplitArray end function table_nums(t) local count = 0 for k, v in pairs(t) do count = count + 1 end return count end local function sortFunc(a,b) local numA = tonumber(a) local numB = tonumber(b) if numA ~= nil and numB ~= nil then return numA < numB else return a < b end end -- 根据Key排序 :从小到大 function pairsByKeys (t) local a = {} for n in pairs(t) do table.insert(a, n) end table.sort(a, sortFunc) local i = 0 -- iterator variable local iter = function () -- iterator function i = i + 1 if a[i] == nil then return nil else return a[i], t[a[i]] end end return iter end local function sortFuncEx(a,b) local numA = tonumber(a) local numB = tonumber(b) if numA ~= nil and numB ~= nil then return numA > numB else return a > b end end -- 根据Key排序(从大到小) function pairsByKeysEx (t) local a = {} for n in pairs(t) do table.insert(a, n) end table.sort(a, sortFuncEx) local i = 0 -- iterator variable local iter = function () -- iterator function i = i + 1 if a[i] == nil then return nil else return a[i], t[a[i]] end end return iter end -- 将 path 中的 str_old 替换为 str_new -- IOS 的路径中包含'-'符号,使用 string.gsub 进行替换会失败 -- 所有手动写一个替换的接口,用于转换路径 function replace_path(path, str_old, str_new) local len_old = string.len(str_old) local len_new = string.len(str_new) local file = string.sub(path,len_old + 1,-1) local path_new = str_new .. file return path_new; end -- 删除目录以及目录下的所有文件 function remove_dir(path) for file in lfs.dir(path) do if file ~= "." and file ~= ".." then local f = path..'/'..file local attr = lfs.attributes (f) assert (type(attr) == "table") if attr.mode == "directory" then if remove_dir(f) == false then return false; end else os.remove(f); end end end lfs.rmdir(path) return true; end -- 遍历dir中的所有文件,rev表示是否遍历子目录,fun回调文件名 function for_dir (path, fun) for file in lfs.dir(path) do if file ~= "." and file ~= ".." then local f = path..'/'..file -- logD(f) local attr = lfs.attributes (f) assert (type(attr) == "table") if attr.mode == "directory" then if for_dir (f,fun) == false then return false; end else -- logD(file) if fun(f, file, path) == false then return false; end end end end return true; end function move_file(file_source, file_target) --logD("PreloadTools::move_file() file_source = " .. tostring(file_source)) --logD("PreloadTools::move_file() file_target = " .. tostring(file_target)) if not cc.FileUtils:getInstance():isFileExist(file_source) then logD("PreloadTools::move_file() file_source is not exist : " .. tostring(file_source)) return false end -- 删除旧的文件 if cc.FileUtils:getInstance():isFileExist(file_target) then logD("PreloadTools::move_file() remove old file : " .. tostring(file_target)) os.remove(file_target); end -- 替换成新的文件 local ret1, ret2= os.rename(file_source, file_target) if not ret1 then logD("PreloadTools::move_file() move file failed, ret2 = " .. tostring(ret2) .. ", source = " .. file_source .. ", target = " .. file_target) return false; end return true; end -- 移动目录下的所有文件到指定目录 function move_dir(path_source, path_target) logD("PreloadTools::move_dir() path_source = " .. tostring(path_source)) logD("PreloadTools::move_dir() path_target = " .. tostring(path_target)) if not path_source or not path_target then return false end if not cc.FileUtils:getInstance():isDirectoryExist(path_target) then if not cc.FileUtils:getInstance():createDirectory(path_target) then logD("PreloadTools::move_dir() createDirectory failed " .. path_target) return false end end local ret = true; local version_files = {} for_dir(path_source, function(fullpath, file, dir) --logD("PreloadTools::move_dir() for_dir: " .. fullpath) local dirNew = replace_path(dir, path_source, path_target) local fullpathNew = replace_path(fullpath, path_source, path_target) --logD("PreloadTools::move_dir() for_dir: dirNew = " .. dirNew) --logD("PreloadTools::move_dir() for_dir: fullpathNew = " .. fullpathNew) if not cc.FileUtils:getInstance():isDirectoryExist(dirNew) then --logD("PreloadTools::move_dir() create directory : " .. tostring(dirNew)) if not cc.FileUtils:getInstance():createDirectory(dirNew) then logD("PreloadTools::move_dir() create directory failed :" .. dirNew) ret = false; end end -- 版本文件最后处理 if file == "version.json" then table.insert(version_files, {fullpath = fullpath, fullpathNew = fullpathNew}) return end -- 移动文件 if not move_file(fullpath, fullpathNew) then ret = false end --logD("PreloadTools::move_dir() move file successed, source = " .. fullpath .. ", target = " .. fullpathNew) end) logD("PreloadTools::move_dir() ret = " .. tostring(ret)) -- 移动文件成功之后,最后才移动版本文件 if ret then if #version_files > 0 then for _,v in pairs(version_files) do --logI("PreloadTools::move_dir() move file, source = " .. v.fullpath .. ", target = " .. v.fullpathNew) if not move_file(v.fullpath, v.fullpathNew) then logD("PreloadTools::move_dir() move file failed, source = " .. v.fullpath .. ", target = " .. v.fullpathNew) end end end end logD("PreloadTools::move_dir() finished") return ret; end -- 在下一帧执行一次函数func function runInNextFrame(func , ...) local id local arg = {...} local function exec() cc.Director:getInstance():getScheduler():unscheduleScriptEntry(id); func(unpack(arg)); end id = cc.Director:getInstance():getScheduler():scheduleScriptFunc(exec, 0, false) end function runDelayWithTime(func, mtime) local id local function exec() cc.Director:getInstance():getScheduler():unscheduleScriptEntry(id); func(); end id = cc.Director:getInstance():getScheduler():scheduleScriptFunc(exec, tonumber(mtime), false) return id end function isIpV6Format(ip) local ret = string.find(ip, "%:") return ret ~= nil end function getHostByUrl(url) logD("getHostByUrl()", url) local isHost = false; local isHttps = false local withHead = string.find(url, "https") if withHead and withHead > 0 then isHttps = true end local withHead = string.find(url, "http") if withHead and withHead > 0 then url = string.gsub(url, "http://", ""); url = string.gsub(url, "https://", ""); end local arr1 = split(url, "/") local host = "" if arr1 and #arr1 > 0 then host = arr1[1] end local arr2 = split(host, "%.") if arr2 and #arr2 > 0 then local num = tonumber(arr2[1]) if num == nil then isHost = true end end logD("getHostByUrl()", isHost, host) return isHost, host ,isHttps; end -- callback = function(host, ip) function getHostAndIpByUrl(url, callback) logD("getHostAndIpByUrl()", url) local function doCallback(host, ip) logD("getHostAndIpByUrl() doCallback()", host, ip) if callback then callback(host, ip) end end local isHost, host ,isHttps = getHostByUrl(url) -- 如果不包含域名,则返回空 if not isHost then doCallback(); return; end if PluginHttpDns and targetPlatform >= 3 and targetPlatform <= 5 then local function onHttpDnsResponse(strResult) logD("onHttpDnsResponse() strResult = ", tostring(strResult)); -- 解析结果 local jsonResult = json.decode(tostring(strResult)) if not jsonResult then logD("onHttpDnsResponse() jsonResult is nil") return doCallback(); end -- 检查错误码 local code = tonumber(jsonResult.code) if code ~= 8001 then return doCallback(); end logD("onHttpDnsResponse() message = ", tostring(jsonResult.message)) -- 解析内容 local jsonMessage = json.decode(jsonResult.message) if not jsonMessage then logD("onHttpDnsResponse() jsonMessage is nil") return doCallback(); end if type(jsonMessage) == "table" then for k,v in pairs(jsonMessage) do logD(k,v) end local ip = jsonMessage[1] return doCallback(host, ip); else logD("type of jsonMessage is ",type(jsonMessage)); return doCallback(); end end local params = { host = isHttps and "https://"..host or "http://"..host, callback = onHttpDnsResponse } PluginHttpDns:callVoid("getIpByHostWithNormal", params); else doCallback(); end end -- callback = function(url, headers) function converUrlToIp(url, callback) logD("converUrlToIp() url = ", url) local function doCallback(urlNew, header) logD("converUrlToIp() doCallback() ", urlNew) if callback then callback( urlNew or url, header) end end -- 微信头像不使用HTTPDNS local strWeiXin = "thirdwx.qlogo.cn" local ret = string.find(url, strWeiXin) if ret then logD("converUrlToIp() return by thirdwx.qlogo.cn"); return doCallback(); end -- 如果明确指示不使用HTTPDNS if RomSetting.withoutHttpDns then logD("converUrlToIp() return by withoutHttpDns"); return doCallback(); end -- 查询这个url中的host和Ip,并进行处理 getHostAndIpByUrl(url, function(host, ip) if host and ip then local isIpV6 = isIpV6Format(ip) if isIpV6 then ip = "[" .. ip .. "]" end local urlNew = string.gsub(url, host, ip); local header = { Host = host, } doCallback(urlNew, header) else doCallback() end end) end -- 递交一个http post请求,通过callback返回 -- handlerCallback: 返回 post 的句柄 function httpPost(url , postTable , callback, handlerCallback) --logD("httpPost() url = ", url) converUrlToIp(url, function(urlNew, header) -- -- 添加md5验证 begin -- if postTable.action ~= "system.init" then local key_table = {} --取出所有的键 for key,_ in pairs(postTable) do table.insert(key_table,key) end --对所有键进行排序 local str = "" table.sort(key_table) for _,key in pairs(key_table) do if _ == #key_table then local Md5key = "s#z7*wk^z(m2u%er@vgf8h&ds#)|sg"; str = str..""..key.."="..postTable[key].."&".."key="..Md5key else str = str..""..key.."="..postTable[key].."&" end end print("输出"..str) local signtoken = md5.sumhexa( str ) local signtokenLower = string.lower(signtoken); print("输出signtoken小写"..signtokenLower) postTable.signtoken = signtokenLower -- end -- 添加md5验证 end header = header or {} header["Expect"] = "" logD("httpPost() url = ", url) logD("httpPost() urlNew = ", urlNew) if table and table.tostring then logD("httpPost() header = ", table.tostring(header)) logD("httpPost() postTable = ", table.tostring(postTable)) else for k,v in pairs(header) do logD(string.format("httpPost() header: %s = %s ", k, v)) end for k,v in pairs(postTable) do logD(string.format("httpPost() postTable: %s = %s ", k, v)) end end local taskId = cc.CURLManager:getInstance():createPostTask(urlNew , header, postTable , callback) if handlerCallback then handlerCallback(taskId) end end) end --- 递交一个带自定义头的post请求 function httpPostWithHeader(url, header, postFields, callback) return cc.CURLManager:getInstance():createPostTask(url , header, postFields , callback) end function closeHttpPost(id) if id then cc.CURLManager:getInstance():cancelTask(id); end end -- 创建下载任务,如果下载失败,就用ip地址下载 function downloadFileByUrls(urls , onUpdate , priority , startPos , dataSize) urls = split(urls , ","); priority = priority or 0; startPos = startPos or 0; dataSize = dataSize or 0; local index = 1; local function createTask(url,onUpdateFirst) converUrlToIp(url, function(urlNew, header) cc.CURLManager:getInstance():createHeaderTask(urlNew ,header, onUpdateFirst , priority , startPos , dataSize); end) end local function onUpdateFirst(status , data) -- 解析域名失败 if status == "failed" and urls[index + 1] ~= nil then logD("使用首选地址下载文件失败" , urls[index] , onUpdateFirst , priority , startPos , dataSize); index = index + 1; logD("使用备用地址开始下载文件" , urls[index] , onUpdateFirst , priority , startPos , dataSize); createTask(urls[index],onUpdateFirst) else onUpdate(status , data); end end logD("创建下载任务" , urls[index] , onUpdateFirst , priority , startPos , dataSize); createTask(urls[index],onUpdateFirst) end function downloadFileByUrls2(urls , onUpdate , fileName , dataSize) urls = split(urls , ","); fileName = fileName or ""; dataSize = dataSize or 0; local index = 1; local function createTask(url,onUpdateFirst) converUrlToIp(url, function(urlNew, header) cc.CurlFileTaskManager:getInstance():createHeaderTask(urlNew , header , onUpdateFirst , fileName , dataSize); end) end local function onUpdateFirst(status , data) -- 下载失败 if status == "failed" and urls[index + 1] ~= nil then logD("使用首选地址下载文件失败" , urls[index] , onUpdateFirst , fileName , dataSize); index = index + 1; logD("使用备用地址开始下载文件" , urls[index] , onUpdateFirst , fileName , dataSize); createTask(urls[index] , onUpdateFirst) else onUpdate(status , data); end end logD("创建下载任务" , urls[index] , onUpdateFirst , fileName , dataSize); createTask(urls[index] , onUpdateFirst) end function saveStringToFile(strText, fileName) if not fileName or fileName == "" then return end local targetPath = writablePath .. fileName; local f , err = io.open(targetPath , "wb"); if f then f:write(strText or ""); f:close(); return true; else return false , err; end end function loadStringFromFile(fileName) if not fileName or fileName == "" then return "" end local strText = getWritableFileData(fileName); return strText; end function saveUserId(userId) cc.UserDefault:getInstance():setStringForKey("UserId", userId); end function loadUserId() local userId = cc.UserDefault:getInstance():getStringForKey("UserId"); return userId or ""; end -- 显示错误界面 function showErrorView(errorString, onClickOk) local view = require("preload.AutoUpdate.ErrorView"):new(errorString, onClickOk); local director = cc.Director:getInstance(); local mainScene = director:getRunningScene() mainScene:addChild(view.ui); end -- 显示一个提示界面 function showTipsView(tipsMessage, onOkCallback, onCancelCallback) local view = require("preload.AutoUpdate.TipsView"):new(tipsMessage, onOkCallback, onCancelCallback); local director = cc.Director:getInstance(); local mainScene = director:getRunningScene() mainScene:addChild(view.ui); end -- 获取唯一字符串 function guid() local seed = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'} local tb = {} for i = 1,32 do table.insert(tb, seed[math.random(1,16)]) end local sid = table.concat(tb) return sid end function guid16() local seed = {'0','1','2','3','4','5','6','7','8','9'} local tb = {} for i = 1,16 do table.insert(tb, seed[math.random(1,10)]) end local sid = table.concat(tb) return sid end -- 检查文件列表中的文件是否都存在 --[[ files_list_file : 记录文件列表的文件 files_list = { [filename] = md5_value, [filename] = md5_value, [filename] = md5_value, [filename] = md5_value, }, 如果文件完整,return true, nil 如果文件缺失, return false, missing_file_list --]] function checkFilesExist(files_list_file) logD("PreloadTools::checkFilesExist(), files_list_file = ", tostring(files_list_file)) -- 文件是否存在 local isExist = isFileExist(files_list_file) if not isExist then logE("PreloadTools::checkFilesExist() files_list_file is not exist"); return false, {} end -- 读取文件内容 local filestring = getFileData(files_list_file) if not filestring or filestring == "" then logE("PreloadTools::checkFilesExist() filestring is nil or empty"); return false, {} end -- 解密文件内容 local jsonString = base64.decode(filestring) if not jsonString or jsonString == "" then logE("PreloadTools::checkFilesExist() jsonString is nil or empty"); return false, {}; end -- 转 json object local jsonData = json.decode(jsonString); if not jsonData then logE("PreloadTools::checkFilesExist() jsonData is nil"); return false, {}; end -- 打印文件列表 --[[ for k,v in pairs(jsonData) do logD(v, " : ", k) end --]] local ret = true local missing_file_list = {} for fileName,v in pairs(jsonData) do -- 之前的文件列表中,文件名是以"/"开头的,这会让C++认为这是一个完整路径 local firstChar = string.sub(fileName, 1, 1) if firstChar == "/" then fileName = string.sub(fileName, 2) end local isExist = isFileExist(fileName) --logD(string.format("checkFilesExist(), ret = %s, fileName = %s", tostring(isExist), tostring(fileName))); if not isExist then ret = false missing_file_list[fileName] = v end end logD("checkFilesExist(), ret = ", tostring(ret)) for fileName,v in pairs(missing_file_list) do logD(string.format("checkFilesExist(), ret = false, fileName = %s", tostring(fileName))); end return ret, missing_file_list end local g_phpUrl=nil local g_phpUrlIdx = 0 local g_phpUrlList = {} -- 设置当前使用成功的phpUrl local function setGlobalPhpUrl(url) logD("setGlobalPhpUrl() ", url) g_phpUrl = url end function getGlobalPhpUrl() return g_phpUrl or RomSetting.phpUrl end -- 保存最后一次使用成功的 phpUrl local function saveLastPhpUrl(url) logD("saveLastPhpUrl() ", url) cc.UserDefault:getInstance():setStringForKey("lastPhpUrl", url or "") end -- 读取最后一次使用成功的 phpUrl local function loadLastPhpUrl() local lastPhpUrl = cc.UserDefault:getInstance():getStringForKey("lastPhpUrl", "") logD("loadLastPhpUrl() ", lastPhpUrl) return lastPhpUrl end function initGlobalPhpUrlList() --local isReview = cc.UserDefault:getInstance():getBoolForKey("isReview", true); -- 加载上次成功的phpUrl local lastPhpUrl = loadLastPhpUrl() -- if lastPhpUrl and lastPhpUrl ~= "" then -- table.insert(g_phpUrlList, lastPhpUrl) -- end -- 按顺序加载配置中的phpUrl if RomSetting.phpUrl then table.insert(g_phpUrlList, RomSetting.phpUrl) end if RomSetting.phpUrl_1 then table.insert(g_phpUrlList, RomSetting.phpUrl_1) end if RomSetting.phpUrl_2 then table.insert(g_phpUrlList, RomSetting.phpUrl_2) end if RomSetting.phpUrl_3 then table.insert(g_phpUrlList, RomSetting.phpUrl_3) end for k,v in pairs(g_phpUrlList) do logD("initGlobalPhpUrlList", tostring(v)) end end initGlobalPhpUrlList() -- callback : function(true/false) -- useNextUrl :是否使用下一个url function getServerConfigs(callback, useNextUrl) logD("getServerConfigs(), useNextUrl = ", tostring(useNextUrl)) local function doCallback(isSuccessed) if callback then callback(isSuccessed) end end -- 获取当前要使用的phpUrl if useNextUrl then g_phpUrlIdx = g_phpUrlIdx + 1 end local curPhpUrl = g_phpUrlList[g_phpUrlIdx] if not curPhpUrl then logE("getServerConfigs() curPhpUrl is nil") doCallback(false) return; end logD("getServerConfigs(), curPhpUrl = ", curPhpUrl) local uid = loadUserId(); local apkver = tostring(getAppVersion()); local resver = loadVersion(); local params = { appid = tostring(RomSetting.AppId), apkType = tonumber(RomSetting.ChannelId), uid = uid; apkver = apkver, vername = apkver, resver = resver, isnew = 1, } for k,v in pairs(params) do logD("getServerConfigs() params: " .. tostring(k) .. " = " .. tostring(v)) end local PasswordKey = "s#z7*wk^z(m2u%er@vgf8h&ds#)|sg"; local RandomString = guid16(); local strParams1 = json.encode(params) logD("params:",strParams1); local strParams2 = base64.encode(md5.crypt(strParams1, PasswordKey, RandomString)) local tt = { action = "system.init", p = strParams2, } isResponse = false local function onHttpResponse(status, response) logD("getServerConfigs:onHttpResponse()", tostring(status), tostring(response)) -- 标记为收到回复了,不需要关系回复的数据是否正确 isResponse = true if status ~= "successed" then logE("getServerConfigs:onHttpResponse() status not successed") getServerConfigs(callback, true) return end local jsonData = json.decode(response) if not jsonData then logE("getServerConfigs:onHttpResponse() jsonData is nil") getServerConfigs(callback, true) return end if jsonData.code ~= 200 then logE("getServerConfigs:onHttpResponse() jsonData.code == ", jsonData.code) if jsonData.code == -105 then -- 停服公告 showTipsView("系统维护中,请稍后重试!", function() cc.Application:getInstance():shutdown(); end) else getServerConfigs(callback, true) end return end if not jsonData.result then logE("getServerConfigs:onHttpResponse() jsonData.result is nil") getServerConfigs(callback, true) return; end local strResult = md5.decrypt(base64.decode(jsonData.result), PasswordKey); logD("getServerConfigs:onHttpResponse() strResult = ", strResult) local jsonResult = json.decode(strResult); if not jsonResult or type(jsonResult) ~= "table" then logE("getServerConfigs:onHttpResponse() jsonResult is not valid") getServerConfigs(callback, true) return end -- 记录当前可用的phpUrl saveLastPhpUrl(curPhpUrl) setGlobalPhpUrl(curPhpUrl) -- 保存服务器配置信息 for k,v in pairs(jsonResult) do PhpSetting[k] = v end --PhpSetting.gameServer = "47.107.98.44:9240" -- 保存服务器下发的审核状态 -- 如果本地是审核状态,而现在服务器下发时非审核状态,则保存状态后重启 local curReviewStatus = isReviewVersion() local newReviewStatus = tonumber(PhpSetting.isAudit) == 1 if curReviewStatus ~= newReviewStatus then saveIsReview(newReviewStatus) logD("getServerConfigs:onHttpResponse() RomSetting.ChannelId = " .. tostring(RomSetting.ChannelId)) logD("getServerConfigs:onHttpResponse() RomSetting.IosReviewType = " .. tostring(RomSetting.IosReviewType)) if RomSetting.IosReviewType and RomSetting.IosReviewType ~= 1 then logD("getServerConfigs:onHttpResponse() 审核版本转非审核版本") showTipsView("点击确定退出游戏,再次启动游戏即可", function() cc.Application:getInstance():shutdown(); end) return; end end -- 如果服务器要求上传日志,则立刻上传 if jsonResult.upload_log ~= nil and jsonResult.upload_log ~= "" then logD("getServerConfigs::onHttpResponse() upload_log = ", upload_log); if logFileManager then logD("getServerConfigs::onHttpResponse() request upload"); logFileManager:uploadFilesByDay(tostring(jsonResult.upload_log)) end end doCallback(true) end --[[ 存在一种情况,HttpDns初始化的时间比较长,可能达到15甚至20s. HttpDns返回结果的时候,脚本已经在使用ip连接了。 然后HttpDns的回调又会触发host连接。 这样就有了两个连接,且都是有效的。 导致后面更新出现一些重复的流程而产生问题 --]] logD("getServerConfigs() 打印0") local taskId; local function onCreatePostCallback(id) taskId = id; runDelayWithTime(function() logD("getServerConfigs() 打印1") if not isResponse then --没有数据回来 默认超时 logD("getServerConfigs() 打印2") -- 取消之前的连接 if taskId then logD("getServerConfigs() 打印3") cc.CURLManager:getInstance():cancelTask(taskId) end -- 换一个地址来尝试 getServerConfigs(callback, true) end end, 5) end httpPost(curPhpUrl, tt, onHttpResponse, onCreatePostCallback); end