Cocos2d-X与游戏开发cocos2d-xcocos2d

cocos2d lua 热更新源码研究(AssetsManage

2018-03-09  本文已影响43人  90d81be3ec65
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、困惑起因
void AssetsManager::update()
{
    // all operation in checkUpdate, nothing need to do
    // keep this function for compatibility
}
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;
}
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;
}
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
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
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);
           }
       }
   };
}
_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);
};
上一篇下一篇

猜你喜欢

热点阅读