美文网首页cocos2dcocos2d-Lua
9.Quick-cocos2dx热更新客户端实现

9.Quick-cocos2dx热更新客户端实现

作者: 会写诗的翩翩少年 | 来源:发表于2017-07-15 11:37 被阅读52次

0.前言
  本文介绍的是热更新客户端实现,本文的阅读可结合上文,热更新的客户端实现大致分为以下几个步骤:
  1.修改资源搜索路径,使热更之后,游戏能优先加载热更资源
  2.加载本地资源清单Reslist
  3.请求远程资源清单替换本地资源清单
  4.对照资源清单检查本地资源,有的则在清单中标记,没有的则删除
  5.请求资源清单中未标记的资源
  6.加载资源清单中的代码资源
  7.热更结束,回调主逻辑

1.使用方式

local CCHotFix = require("app.scenes.CCHotFix")
CCHotFix.new(handler(self, function(self)
    end))

2.代码阅读
  代码很简单,注释很清晰,阅读建议就是将代码拷贝至sublime(个人感觉看着舒服一些),逐行阅读,开始吧!

require("lfs")
local CCHotFix = class("CCHotFix")

--游戏版本号
VERSION_C_GAME = 1
--资源清单名
local NAME_C_RES_LIST = "ResList"
--服务器路径
local PATH_C_SERVER_URL = "ftp://localhost/"
--资源路径
local PATH_C_HOTFIX_RES = device.writablePath .. "upd/Res/"
--临时资源路径
local PATH_C_HOTFIX_RES_TMP = device.writablePath .. "upd/ResTmp/"
--资源清单路径
local PATH_C_HOTFIX_RES_LIST = device.writablePath .. "upd/" .. NAME_C_RES_LIST

function CCHotFix:ctor(onComplete)
    --热更结束的回调
    self.onComplete = onComplete

    --资源文件夹创建
    cc.FileUtils:getInstance():createDirectory(PATH_C_HOTFIX_RES)
    cc.FileUtils:getInstance():createDirectory(PATH_C_HOTFIX_RES_TMP)

    --修改资源搜索路径
    cc.FileUtils:getInstance():addSearchPath(PATH_C_HOTFIX_RES)
    cc.FileUtils:getInstance():addSearchPath("res/")

    --检测是否存在资源清单
    if cc.FileUtils:getInstance():isFileExist(PATH_C_HOTFIX_LIST) then 
        self.ResList = dofile(PATH_C_HOTFIX_RES_LIST)
        VERSION_C_GAME = self.ResList.ver
    end

    --请求服务器上的资源清单
    self:requestResList()
end

--从服务器请求文件
function CCHotFix:requestFileFromServer(url, succ, err)
    local url = PATH_C_SERVER_URL .. url
    local request = network.createHTTPRequest(function(event)
        if event.name == "completed" then           
            local rscode = event.request:getResponseStatusCode()            
            if rscode == 226 then               
                succ(event.request:getResponseData())               
            else
                err()
            end
        elseif event.name == "progress" then
        else
            err()
        end
    end, url, "GET")
    request:setTimeout(15)
    request:start()
end

--遍历路径
function CCHotFix:traversePath(rootpath, func)
    for entry in lfs.dir(rootpath) do
        if entry ~= '.' and entry ~= '..' then
            local path = rootpath .. '\\' .. entry
            local attr = lfs.attributes(path)
            assert(type(attr) == 'table')               
            if attr.mode == 'directory' then
                self:traversePath(path)
            else
                func(path)
            end
        end
    end
end

--请求资源列表
function CCHotFix:requestResList()
    self:requestFileFromServer(NAME_C_RES_LIST,
        handler(self, function(self, data)
            --请求成功后,将其写入本地路径,并加载
            io.writefile(PATH_C_HOTFIX_RES_LIST, data, "wb+")
            self.ResList = dofile(PATH_C_HOTFIX_RES_LIST)

            --根据资源清单对本地资源进行检测
            self:checkUpdRes()
        end),
        handler(self, function(self)
            --本地和服务器都无资源清单
            if not self.ResList then
                self.onComplete()
            else  --本地有,远程请求失败的情况
                self:checkUpdRes()
            end         
        end))
end

function CCHotFix:checkUpdRes()
    --遍历本地资源路径
    self:traversePath(PATH_C_HOTFIX_RES, handler(self, function(self, path)
        local keep = false
        local md5 = string.lower(crypto.md5file(path))
        
        --检测该文件的md5是否存在于资源清单
        for i, v in ipairs(self.ResList.stage) do
            if string.lower(v.code) == md5 then
                local arr = string.split(path, "/")
                local name = table.remove(arr, #arr)
                local path = table.concat(arr, "/") .. "/"
                if name ~= v.name then  --与资源清单上的名字不同则重命名
                    cc.FileUtils:getInstance():renameFile(path, name, v.name)
                end

                --存在则标记资源清单
                v.fileCheck = true
                keep = true
                break
            end
        end

        --该文件不存在于资源清单,则删除该文件
        if not keep then
            cc.FileUtils:getInstance():removeFile(path)
        end
    end))

    --请求资源清单上未标记的资源
    self:requestUncheckRes()
end

function CCHotFix:requestUncheckRes()
    --将未标记资源写入对象存储
    self.uncheckRes = {}
    for i, v in ipairs(self.ResList.stage) do
        if not v.fileCheck then
            table.insert(self.uncheckRes, v.code)
        end
    end
    
    --一次下载一个资源文件
    self.downloadNext = function(self)
        local path = table.remove(self.uncheckRes)
        if path then
            self:requestFileFromServer(path,
                handler(self, function(self, data)
                    --请求成功后,写入tmp路径
                    io.writefile(PATH_C_HOTFIX_RES_TMP .. path, data, "wb+")
                    self:downloadNext()
                end),
                handler(self, function(self)
                    print("请求资源失败,热更新停止")
                    cc.FileUtils:getInstance():removeDirectory(PATH_C_HOTFIX_RES_TMP)
                    self.onComplete()
                end))
        else
            print("下载完毕")
            self:movTmpRes()
        end
    end
    self:downloadNext()
end

--将tmp路径下的资源写入正式路径下
function CCHotFix:movTmpRes()
    for i, v in ipairs(self.ResList.stage) do
        if not v.fileCheck then
            v.fileCheck = true
            os.rename(PATH_C_HOTFIX_RES_TMP .. v.code, PATH_C_HOTFIX_RES .. v.name)
        end
    end
    self:loadZip()
end

--加载热更下来的代码资源
function CCHotFix:loadZip()
    for i, v in ipairs(self.ResList.stage) do
        if v.act == "load" then
            cc.LuaLoadChunksFromZIP(PATH_C_HOTFIX_RES .. v.name)
        end
    end

    VERSION_C_GAME = self.ResList.ver
    self.onComplete()
end

return CCHotFix

相关文章

  • 9.Quick-cocos2dx热更新客户端实现

    0.前言本文介绍的是热更新客户端实现,本文的阅读可结合上文,热更新的客户端实现大致分为以下几个步骤:1.修改资源搜...

  • UNITY3D 热更新

    何谓热更新 Unity3D热更新就是指:用户重启客户端就能实现客户端资源代码更新的需求或者功能。 为何热更新 热更...

  • Lua脚本热更新

    本文继续来写一下脚本代码的热更新在游戏客户端或服务端的实现,之前写了一篇【客户端python热更新】里面提到热更新...

  • 客户端热更新机制实现

    客户端热更新机制实现 客户端和服务器端各自维护两个版本描述文件: 来自chcp.json: 来自chcp.mani...

  • 使用JSPatch实现iOS客户端热更新

    首先没有JSPatch帐号的去官网注册帐号JSPatch注册入口(可以使用fir.im帐号直接登录)。 集成sdk...

  • 热更新客户端配置

    参考文档 https://www.jianshu.com/p/ca795f03e12d最新https://segm...

  • 客户端python热更新

    介绍: 热更新,就是在维持服务不间断的情况下,对软件代码逻辑或配置数据进行更新修复。随着游戏项目引入了脚本语言以后...

  • Cordova 实现热更新

    文章来源 http://blog.csdn.net/zhuzhiqiang_zhu/article/detail...

  • Cordova热更新实现

    cordova-hot-code-push-plugin npm cordova-hot-code-push gi...

  • 实现iOS热更新

    参考来自:http://www.jianshu.com/p/8cec322531aeJSPatch,也许也有很多人...

网友评论

  • 最怕认真:你的cocos版本是多少,为什么不用AssetsManagerEx呢
    最怕认真:@会写诗的翩翩少年 这应该是你们自己封装的吧~,官方的热更新,偷偷告诉你!TM的有BUG,根本不支持断点续传,干TM的,我尼玛把源码硬是看了一遍,这哪是做游戏,这是做引擎,而且去官方找说法,有人回答是不存在的,官方装死,本事一流!
    会写诗的翩翩少年:@最怕认真 用的是quick3.6.3,公司用的是这个:joy:

本文标题:9.Quick-cocos2dx热更新客户端实现

本文链接:https://www.haomeiwen.com/subject/hsvahxtx.html