美文网首页
cocos2d-lua热更新

cocos2d-lua热更新

作者: Jey | 来源:发表于2020-05-14 17:36 被阅读0次

    第一种:自己定义文件的对比方式,下载到指定文件夹

    1. https://www.bbsmax.com/A/QV5Zj4365y/
    2. https://www.cnblogs.com/creeper/p/4978247.html

    第二种:使用cocos推荐的那一套manifest+ cc.AssetsManagerEx
    下面是python脚本,生成manifest文件的,加密也一起做了

    #coding:utf-8
    # 使用方法
    # 1.把要生成的文件放入 项目/version文件夹
    # 2.cd 项目目录
    # 3.python py目录
    
    import os
    import hashlib
    import time
    import sys
    import shutil
    
    assetsDir = {
        # ll来
        "search" : ["src", "res"],
        "ignorDir" : ["cocos", "framework", ".svn"],
        "ignorFile":[".DS_Store"],
    }
    #
    def getFileMd5(filename):
        if not os.path.isfile(filename):
            return
        myhash = hashlib.md5()# create a md5 object
        f = file(filename,'rb')
        while True:
            b = f.read(8096)# get file content.
            if not b :
                break
            myhash.update(b)#encrypt the file
        f.close()
        return myhash.hexdigest()
     
    def getFile_md5_value(path, prefix):
        global xml
        fl = os.listdir(path) # get what we have in the dir.
    
        for f in fl:
            if os.path.isdir(os.path.join(path,f)): # if is a dir.
                if prefix == '':
                    getFile_md5_value(os.path.join(path,f), f)
                else:
                    if (f[0] == '.' or (f in assetsDir["ignorDir"])):
                        pass
                    else:
                        getFile_md5_value(os.path.join(path,f), prefix + '/' + f)
    #        else:
            elif (os.path.isfile(path + '/' + f)) and (f not in assetsDir["ignorFile"]):
                md5 = getFileMd5(os.path.join(path,f))
                xml += "\n\t\t\"%s\" : {\n\t\t\t\"md5\" : \"%s\"\n\t\t}, " % (prefix + '/' + f, md5) # output to the md5 value to a string in xml format.
                
    # 判断python
    def _check_python_version():
        major_ver = sys.version_info[0]
        if major_ver > 2:
            print ("The python version is %d.%d. But python 2.x is required. (Version 2.7 is well tested)\n"
                   "Download it here: https://www.python.org/" % (major_ver, sys.version_info[1]))
            return False
    
        return True
    
    def copyFileToPath(path):
        tempPath = path
        if os.path.exists(tempPath):
            
            shutil.rmtree(tempPath)  
            os.mkdir(tempPath)  
            print('-------清除之前资源------')      
    
        copyFiles(os.getcwd() + '/res', tempPath+ '/res')
        copyFiles(os.getcwd() + '/src', tempPath+ '/src_temp')
        print('-------拷贝资源完成---------------')
    
    # 拷贝文件夹到目标文件夹
    copyFileCounts = 0
    def copyFiles(sourceDir, targetDir):
        global copyFileCounts
        print (sourceDir)
        print (u"%s 当前处理文件夹%s已处理%s 个文件" %(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())), sourceDir,copyFileCounts))
        for f in os.listdir(sourceDir):
            sourceF = os.path.join(sourceDir, f)
            targetF = os.path.join(targetDir, f)
            if os.path.isfile(sourceF):
                #创建目录
                if not os.path.exists(targetDir):
                    os.makedirs(targetDir)
                    copyFileCounts += 1
                #文件不存在,或者存在但是大小不同,覆盖
                if not os.path.exists(targetF) or (os.path.exists(targetF) and (os.path.getsize(targetF) != os.path.getsize(sourceF))):
                    #2进制文件
                    open(targetF, "wb").write(open(sourceF, "rb").read())
                    print (u"%s %s 复制完毕" %(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())), targetF))
                else:
                    print (u"%s %s 已存在,不重复复制" %(time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time())), targetF))
            if os.path.isdir(sourceF):
                copyFiles(sourceF, targetF)
    
    
    if __name__ == "__main__":
        if not _check_python_version():
            exit()
        timeStr = time.strftime("%Y%m%d%H%M%S",time.localtime(time.time()))
        if not os.path.exists(os.getcwd() + '/manifest'):
            os.mkdir(os.getcwd() + '/manifest')
        
        sourcePath = os.getcwd() + '/Jey_test'
        # 拷贝
        copyFileToPath(sourcePath)
    
        print('----------加密src-------------')
        # 执行加密lua脚本 Jey_key1_xxxxx  Jey_key2_xxxxx是秘钥
        os.system("cocos luacompile -s "+sourcePath+"/src_temp -d "+sourcePath+"/src -e -k Jey_key1_xxxxx -b Jey_key2_xxxxx --disable-compile")
    
        print ('--------开始生成manifest----->%s' %(os.getcwd() + '/manifest'))
        xml = '{\
        \n\t"packageUrl" : "http://192.168.8.xx/myupdate",\
        \n\t"remoteVersionUrl" : "http://192.168.8.xx/manifest/version.manifest",\
        \n\t"remoteManifestUrl" : "http://192.168.8.xx/manifest/project.manifest",\
        \n\t"version" : "0.0.%s",\
        \n\t"engineVersion" : "Cocos2d-x v3.10",\
        \n\n\t"assets" : {' % timeStr
        getFile_md5_value(sourcePath, '')
        xml = xml[:-2]
        xml += '\n\t},\
        \n\t"searchPaths" : [\
        \n\t]\
        \n}'
        f = file("manifest/project.manifest", "w+")
        f.write(xml)
        print '----------generate version.manifest finish.--------'
        
        #generate version.manifest
        xml = '{\
        \n\t"packageUrl" : "http://192.168.8.xx/myupdate/",\
        \n\t"remoteVersionUrl" : "http://192.168.8.xx/manifest/version.manifest",\
        \n\t"remoteManifestUrl" : "http://192.168.8.xx/manifest/project.manifest",\
        \n\t"version" : "0.0.%s",\
        \n\t"engineVersion" : "Cocos2d-x v3.10"\n}' % timeStr
        f = file("manifest/version.manifest", "w+")
        f.write(xml)
        print '----------generate version.manifest finish.--------'
    
    

    对模块更新不重启的话

    function reload_module(module_name)
        local old_module = _G[module_name]
    
        package.loaded[module_name] = nil
        require (module_name)
    
        local new_module = _G[module_name]
        for k, v in pairs(new_module) do
            old_module[k] = v
        end
    
        package.loaded[module_name] = old_module
    end
    

    在入口main

    -- main.lua
    cc.FileUtils:getInstance():setPopupNotify(false)
    cc.FileUtils:getInstance():addSearchPath("src/")
    cc.FileUtils:getInstance():addSearchPath("res/")
    
    require "config"
    require "cocos.init"
    
    local MyUpdateLayer = require ('MyUpdateLayer')
    
    local G_UPDATE_CONFIG = {
        manifestPath = cc.FileUtils:getInstance():getWritablePath() .."_hot_game_update_/" .. "hall/",
        manifestFile = "res/version/project.manifest",
    }
    
    local function main()
        -- require("app.MyApp"):create():run()
        -- require("updateLayer")(G_UPDATE_CONFIG, function(...)
        --     require("app.MyApp"):create():run()
        -- end, updateAssetsManager)
        local aclayer = MyUpdateLayer.new(function(flag)
            print('flag==='..flag)
            require("app.MyApp"):create():run()
        end)
        local curScene = cc.Scene:create()
        local sharedDirector = cc.Director:getInstance()
    
        if sharedDirector:getRunningScene() then
            sharedDirector:replaceScene(curScene)
        else
            sharedDirector:runWithScene(curScene)
        end
        curScene:addChild(aclayer)
    end
    
    local status, msg = xpcall(main, __G__TRACKBACK__)
    if not status then
        print(msg)
    end
    
    local AssetsManager = class("AssetsManager",function ()
        return cc.LayerColor:create(cc.c4b(20, 20, 20, 220))
    end)
     
    function AssetsManager:ctor(endBack)
        self.endBack = endBack
        self:onNodeEvent("exit", handler(self, self.onExitCallback))
        self:initUI()
        self:setAssetsManage()
    end
     
    function AssetsManager:onExitCallback()
        self.assetsManagerEx:release()
    end
     
    function AssetsManager:initUI()
     
        -- local hintLabel = cc.Label:createWithTTF("正在更新...", '', 20)
        --     :addTo(self)
        --     :move(600, 80)
     
        local progressBg = display.newSprite("progressBg.png")    
            :addTo(self)
        progressBg:setPosition(display.cx, 100)
        
        self.progress = cc.ProgressTimer:create(display.newSprite("progress.png"))
            :addTo(progressBg)
            :move(380, 19)
        self.progress:setType(cc.PROGRESS_TIMER_TYPE_BAR)
        self.progress:setBarChangeRate(cc.p(1, 0))
        self.progress:setMidpoint(cc.p(0.0, 0.5))
        self.progress:setPercentage(0) 
     
        --触摸吞噬
        self.listener = cc.EventListenerTouchOneByOne:create()
        self.listener:setSwallowTouches(true)
        local onTouchBegan = function (touch, event)
            return true
        end
     
        self.listener:registerScriptHandler(onTouchBegan, cc.Handler.EVENT_TOUCH_BEGAN)
        cc.Director:getInstance():getEventDispatcher():addEventListenerWithSceneGraphPriority(self.listener, self)   
    end
     
    function AssetsManager:setAssetsManage()
        --创建可写目录与设置搜索路径
        local storagePath = cc.FileUtils:getInstance():getWritablePath() .. "_hot_game_update_/" 
        local resPath = storagePath.. '/res/'
        local srcPath = storagePath.. '/src/'
        if not (cc.FileUtils:getInstance():isDirectoryExist(storagePath)) then         
            cc.FileUtils:getInstance():createDirectory(storagePath)
            cc.FileUtils:getInstance():createDirectory(resPath)
            cc.FileUtils:getInstance():createDirectory(srcPath)
        end
        local searchPaths = cc.FileUtils:getInstance():getSearchPaths() 
        table.insert(searchPaths, 1, storagePath)  
        table.insert(searchPaths, 2, resPath)
        table.insert(searchPaths, 3, srcPath)
        cc.FileUtils:getInstance():setSearchPaths(searchPaths)
     
        self.assetsManagerEx = cc.AssetsManagerEx:create("res/version/project.manifest", storagePath)    
        self.assetsManagerEx:retain()
     
        local eventListenerAssetsManagerEx = cc.EventListenerAssetsManagerEx:create(self.assetsManagerEx, 
           function (event)
               self:handleAssetsManagerEvent(event)
           end)
     
        local dispatcher = cc.Director:getInstance():getEventDispatcher()
        dispatcher:addEventListenerWithFixedPriority(eventListenerAssetsManagerEx, 1)
        
        if self.assetsManagerEx:getLocalManifest():isLoaded() then
            print('find-----------localManifest')
            dump(self.assetsManagerEx:getLocalManifest())
        end
        --检查版本并升级
        self.assetsManagerEx:update()
    end
     
    function AssetsManager:handleAssetsManagerEvent(event)    
        local eventCodeList = cc.EventAssetsManagerEx.EventCode    
     
        local eventCodeHand = {
     
            [eventCodeList.ERROR_NO_LOCAL_MANIFEST] = function ()
                print("发生错误:本地资源清单文件未找到")
            end,
     
            [eventCodeList.ERROR_DOWNLOAD_MANIFEST] = function ()
                print("发生错误:远程资源清单文件下载失败")  --资源服务器没有打开,
                self:downloadManifestError()
            end,
     
            [eventCodeList.ERROR_PARSE_MANIFEST] = function ()
                 print("发生错误:资源清单文件解析失败")
            end,
     
            [eventCodeList.NEW_VERSION_FOUND] = function ()
                print("发现找到新版本")
            end,
     
            [eventCodeList.ALREADY_UP_TO_DATE] = function ()
                print("已经更新到服务器最新版本")            
                self:updateFinished()
            end,
     
            [eventCodeList.UPDATE_PROGRESSION]= function ()
                print("更新过程的进度事件")
                self.progress:setPercentage(event:getPercentByFile())
            end,
     
            [eventCodeList.ASSET_UPDATED] = function ()
                print("单个资源被更新事件")
            end,
     
            [eventCodeList.ERROR_UPDATING] = function ()
                print("发生错误:更新过程中遇到错误")
            end,
     
            [eventCodeList.UPDATE_FINISHED] = function ()
                print("更新成功事件")
                self:updateFinished()
            end,
     
            [eventCodeList.UPDATE_FAILED] = function ()
                print("更新失败事件")
            end,
     
            [eventCodeList.ERROR_DECOMPRESS] = function ()
                print("解压缩失败")
            end
        }
        local eventCode = event:getEventCode()    
        if eventCodeHand[eventCode] ~= nil then
            eventCodeHand[eventCode]()
        end  
    end
     
    function AssetsManager:updateFinished()
        self:setVisible(false)
        self.listener:setEnabled(false)
        self.endBack(1)
    end
     
    function AssetsManager:downloadManifestError()
        self:setVisible(false)
        self.listener:setEnabled(false)
        self.endBack(2)
    end
     
    return AssetsManager
    

    相关文章

      网友评论

          本文标题:cocos2d-lua热更新

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