美文网首页
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.bbsmax.com/A/QV5Zj43...

  • 热更新

    参考文章 https://www.jianshu.com/p/2f356e3276b8

  • 热更新

    热更新技术背景 1.热更新定义,APP热更新,就是指软件不通过苹果APP Store的版本更新审核,直接可以自行更...

  • 热更新

    mono热更新 更新过程中强退导致dll损坏 问题的产生是这样的:我们的代码文件随着开发会越来越打,当更新一个 d...

  • 热更新

    需要前端把更新后的代码生成chcp.manifest 第一部: npm i -g cordova-hot-...

  • 热更新

    腾讯热更新 https://gold.xitu.io/post/584a70feac502e00691c4a07 ...

  • 热更新

    一、安装CodePush CLI 在项目根目录下,安装命令: yarn add code-push-cli 安...

  • 热更新

    游戏更新分为两种,一种是游戏内热更,这个不分渠道,所有的游戏包都去游戏的热更服务器去加载资源(一般是资源文件和非底...

  • 热更新

    一.QQ空间超级补丁技术 二.阿里百川HotFix 三.美团Robust 四.微信Tinker 五.QFix

  • 热更新

    腾讯: http://fanhang.me/ios/iosre-geng-xin-ji-chu-ji-yu-bug...

网友评论

      本文标题:cocos2d-lua热更新

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