美文网首页Cocos2d-X与游戏开发cocos2d-xcocos2d
cocos2d lua 热更新源码研究(AssetsManage

cocos2d lua 热更新源码研究(AssetsManage

作者: 90d81be3ec65 | 来源:发表于2018-03-09 17:59 被阅读43次
1、官方的lua热更代码(cocos2d-x-3.16版本)
pathToSave = createDownloadDir() -- createDownloadDir为c++导出给lua的接口

local function onError(errorCode)
    if errorCode == cc.ASSETSMANAGER_NO_NEW_VERSION then
        progressLable:setString("no new version")
    elseif errorCode == cc.ASSETSMANAGER_NETWORK then
        progressLable:setString("network error")
    end
end

local function onProgress( percent )
    local progress = string.format("downloading %d%%",percent)
    progressLable:setString(progress)
end

local function onSuccess()
    progressLable:setString("downloading ok")
end

local function getAssetsManager()
    if nil == assetsManager then
        --增量更新包地址,版本文件地址,存放目录
        assetsManager = cc.AssetsManager:new("https://raw.github.com/samuele3hu/AssetsManagerTest/master/package.zip",
                                       "https://raw.github.com/samuele3hu/AssetsManagerTest/master/version",
                                       pathToSave)
        assetsManager:retain()
        assetsManager:setDelegate(onError, cc.ASSETSMANAGER_PROTOCOL_ERROR) -- 注册错误回调
        assetsManager:setDelegate(onProgress, cc.ASSETSMANAGER_PROTOCOL_PROGRESS) -- 注册进度回调
        assetsManager:setDelegate(onSuccess, cc.ASSETSMANAGER_PROTOCOL_SUCCESS) -- 注册更新成功回调
        assetsManager:setConnectionTimeout(3)
    end

    return assetsManager
end

local function update(sender)
    progressLable:setString("")
    getAssetsManager():checkUpdate() -- checkUpdate() 自带检查版本和更新
end

local function reset(sender)
    progressLable:setString("")

    deleteDownloadDir(pathToSave)

    getAssetsManager():deleteVersion()

    createDownloadDir()
end
2、困惑起因
  • 下面这段代码说update所有的操作都在checkUpdate中了,不需要我们做些什么,保留函数为以后兼容用;而粗略看checkUpdate却未发现哪里处理了下载增量更新包操作,发现只有createDownloadDataTask才有可能做相关操作,那么先跟下去
void AssetsManager::update()
{
    // all operation in checkUpdate, nothing need to do
    // keep this function for compatibility
}
  • AssetsManager.cpp文件:调用createDownloadDataTask(_versionFileUrl)创建下载版本数据的任务
bool AssetsManager::checkUpdate()
{
    if (_versionFileUrl.size() == 0 || _isDownloading) return false;
    
    // Clear _version before assign new value.
    _version.clear();
    _isDownloading = true;
    _downloader->createDownloadDataTask(_versionFileUrl);
    return true;
}
  • CCDownloader.cpp文件: 先new出来一个任务实例task,调用IDownloaderImpl类中的createCoTask(task),添加下载任务
std::shared_ptr<const DownloadTask> Downloader::createDownloadDataTask(const std::string& srcUrl, const std::string& identifier/* = ""*/)
{
    DownloadTask *task_ = new (std::nothrow) DownloadTask();
    std::shared_ptr<const DownloadTask> task(task_);
    do
    {
        task_->requestURL    = srcUrl;
        task_->identifier    = identifier;
        if (0 == srcUrl.length())
        {
            if (onTaskError)
            {
                onTaskError(*task, DownloadTask::ERROR_INVALID_PARAMS, 0, "URL or is empty.");
            }
            task.reset();
            break;
        }
        task_->_coTask.reset(_impl->createCoTask(task));
    } while (0);

    return task;
}
  • CCIDownloaderImpl.h文件:可发现createCoTask是一个纯虚函数,需要子类必须实现,调用子类的createCoTask方法
namespace cocos2d { namespace network
{
    class DownloadTask;

    class CC_DLL IDownloadTask
    {
    public:
        virtual ~IDownloadTask(){}
    };

    class IDownloaderImpl
    {
    public:
        virtual ~IDownloaderImpl(){}

        std::function<void(const DownloadTask& task,
                           int64_t bytesReceived,
                           int64_t totalBytesReceived,
                           int64_t totalBytesExpected,
                           std::function<int64_t(void *buffer, int64_t len)>& transferDataToBuffer)> onTaskProgress;

        std::function<void(const DownloadTask& task,
                           int errorCode,
                           int errorCodeInternal,
                           const std::string& errorStr,
                           std::vector<unsigned char>& data)> onTaskFinish;

        virtual IDownloadTask *createCoTask(std::shared_ptr<const DownloadTask>& task) = 0;
    };

}}  // namespace cocos2d::network
  • CCDownloader-apple.h文件(平台相关):而DownloaderApple类继承了IDownloaderImpl类,实现了createCoTask;此外,在CCDownloader-android.h文件中,DownloaderAndroid类也继承了IDownloaderImpl类,实现了createCoTask,此处就不粘贴代码了
namespace cocos2d { namespace network
{
    class DownloaderHints;
    class DownloaderApple : public IDownloaderImpl
    {
    public:
        DownloaderApple(const DownloaderHints& hints);
        virtual ~DownloaderApple();

        virtual IDownloadTask *createCoTask(std::shared_ptr<const DownloadTask>& task) override;

    private:
        void* _impl;
    };
}}  // namespace cocos2d::network
  • 平台相关下载代码不是重点,这里就不继续分析也无能力深入分析o(╯□╰)o,有兴趣的朋友可以自行跟下去。回归主题,分析到这里究竟还是未找到为什么checkUpdate包含了update的相关操作。那么继续跟下去,直到看到下载成功后的回调,才探索到真理。接下来看CCDownloader.cpp文件,下载任务完成后调用onTaskFinish,再调用函数指针onDataTaskSuccess执行回调
Downloader::Downloader(const DownloaderHints& hints)
{
   DLLOG("Construct Downloader %p", this);
    _impl.reset(new DownloaderImpl(hints));
   _impl->onTaskProgress = [this](const DownloadTask& task,
                                  int64_t bytesReceived,
                                  int64_t totalBytesReceived,
                                  int64_t totalBytesExpected,
                                  std::function<int64_t(void *buffer, int64_t len)>& /*transferDataToBuffer*/)
   {
       if (onTaskProgress)
       {
           onTaskProgress(task, bytesReceived, totalBytesReceived, totalBytesExpected);
       }
   };

   _impl->onTaskFinish = [this](const DownloadTask& task,
                                int errorCode,
                                int errorCodeInternal,
                                const std::string& errorStr,
                                std::vector<unsigned char>& data)
   {
       if (DownloadTask::ERROR_NO_ERROR != errorCode)
       {
           if (onTaskError)
           {
               onTaskError(task, errorCode, errorCodeInternal, errorStr);
           }
           return;
       }

       // success callback
       if (task.storagePath.length())
       {
           if (onFileTaskSuccess)
           {
               onFileTaskSuccess(task);
           }
       }
       else
       {
           // data task
           if (onDataTaskSuccess)
           {
               onDataTaskSuccess(task, data);
           }
       }
   };
}
  • AssetsManager.cpp文件:如下是函数指针onDataTaskSuccessc初始化代码。该函数内容丰富,包含本地版本getVersion()和服务器版本_version的比较,不同才下载增量更新包,也包含下载好的版本_downloadedVersion和服务器版本_version的比较,相同表示已经下载完毕,直接解压,否则调用createDownloadFileTask进行增量更新包下载。分析到这里,那么一切明了,本地版本和服务器版本比较以及增量更新包的更新操作全是在这个回调函数里面(〃'▽'〃)
_downloader->onDataTaskSuccess = [this](const DownloadTask& /*task*/,
                                        std::vector<unsigned char>& data)
{
    // store version info to member _version
    const char *p = (char *)data.data();
    _version.insert(_version.end(), p, p + data.size());
    
    if (getVersion() == _version)
    {
        if (_delegate)
        {
            _delegate->onError(ErrorCode::NO_NEW_VERSION);
        }
        CCLOG("there is not new version");
        // Set resource search path.
        setSearchPath();
        _isDownloading = false;
        return;
    }

    // start download new version assets
    // 1. Urls of package and version should be valid;
    // 2. Package should be a zip file.
    if (_versionFileUrl.empty()
        || _packageUrl.empty()
        || FileUtils::getInstance()->getFileExtension(_packageUrl) != ".zip"
        )
    {
        CCLOG("no version file url, or no package url, or the package is not a zip file");
        _isDownloading = false;
        return;
    }
    
    // Is package already downloaded?
    _downloadedVersion = UserDefault::getInstance()->getStringForKey(keyOfDownloadedVersion().c_str());
    if (_downloadedVersion == _version)
    {
        downloadAndUncompress();
        return;
    }
    
    // start download;
    const string outFileName = _storagePath + TEMP_PACKAGE_FILE_NAME;
    _downloader->createDownloadFileTask(_packageUrl, outFileName);
};

相关文章

  • cocos2d lua 热更新源码研究(AssetsManage

    1、官方的lua热更代码(cocos2d-x-3.16版本) 2、困惑起因 下面这段代码说update所有的操作都...

  • Lua脚本热更新

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

  • Lua-热更新

    什么是热更新 不下线更新/不停机更新最简单的解释就是在操作系统不关软件直接更新,更新期间软件直接用,现在大部分软件...

  • Lua热更新介绍

    介绍演示

  • Cocos2d-lua工程运行流程的理解

    关键词: cocos2d-lua项目启动流程 lua调用cocos2d引擎API 开发环境: 引擎版本:Cocos...

  • lua 源码编译

    lua 源码编译 本文介绍了使用 Visual Studio 编译 lua 源码的方法。 下载源码 源码下载在 这...

  • fusion app自定义事件源码介绍(下)

    安装apk 安装APK(filePath) lua源码 联系QQ(qqNUM) 联系QQ(qqNUM) lua源码...

  • linux软件的安装与升级(lua)

    lua源码组成 lua安装 http://www.lua.org/ftp/lua-5.1.5.tar.gz

  • Unity--Lua热更新

    一、什么是热更新? 一般游戏上线后,玩家下载了第一个版本,在运营的过程中,会不定时的发布新的版本,如果不使用热更新...

  • lua热更新学习

    什么是热更新,对于它的理解,正如云风所说的那样,热更新更多的用途是做不停机的 bug 修复,不应用于常规的版本更新...

网友评论

  • Y攻城狮:楼主在iOS平台试过吗?能通过苹果审核?

本文标题:cocos2d lua 热更新源码研究(AssetsManage

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