cocos2dx上做边下边玩小包热更

因为公司业务需求需要做边下边玩的小包下载,在这里记录一下思路

下载库我使用的是cocos2dx 4.x的CCDownloader来下载文件

大体思路就是hook住fileutils中的getFileData函数和isFileExist函数。

isFileExist:无论初始包里文件是否存在,只要文件是游戏的资源文件这里都要返回“文件存在”

getFileData:这里判断当文件在文件列表中但是游戏包体里不存在该文件时,需要暂停主线程并且去下载文件,文件下载完成时恢复主线程

当暂停主线程时,下载文件的回调需要在子线程中回调否则无法回调成功

除上面的下载文件以外,主线程中根据缺少的文件列表按照一定策略持续下载缺少的文件(优先下载列表等)。

下面是一些主要的代码:

 1 //使用条件变量暂停主线程
 2 //继承了CCFileUtils文件
 3 unsigned char* QFileUtils::getFileData(const char* pszFileName, const char* pszMode, unsigned long * pSize)
 4 {
 5     auto download = QDownloadSmallPack::getInstance();
 6     auto index = QIndex::getInstance();
 7     if (download->isStartCheckRes())
 8     {
 9         bool hasFile = download->checkFile(pszFileName);
10         if (!hasFile)
11         {
12             QIndex::IndexEntry* filePathInIndex = index->getFilePathByIndex(pszFileName);
13             if (filePathInIndex && !filePathInIndex->name.empty())
14             {
15                 std::unique_lock<std::mutex> lock{_m};
16                 download->downloadFile(filePathInIndex, _cond_var);
17                 
18                 if (!download->isDownloadOK)
19                 {
20                     _cond_var.wait(lock, [download](){ return download->isDownloadOK; });
21                 }
22                 
23             }
24         }
25     }
26 
27     return CCFileUtils::getFileData(pszFileName, pszMode, pSize);
28 }
- (id)init: (const cocos2d::network::DownloaderApple*)o hints:(const cocos2d::network::DownloaderHints&) hints
{
    DLLOG("Construct DownloaderAppleImpl %p", self);
    // save outer task ref
    _outer = o;
    _hints = hints;

    // create task dictionary
    self.taskDict = [NSMutableDictionary dictionary];

    // create download session
    NSURLSessionConfiguration *defaultConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
    if (hints.callBackInMainThread)
    {
//在主线程中回调
        self.downloadSession = [NSURLSession sessionWithConfiguration:defaultConfig delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    }
    else
    {
//在子线程中回调
        self.downloadSession = [NSURLSession sessionWithConfiguration:defaultConfig delegate:self delegateQueue:nil];
    }
    
//    self.downloadSession.sessionDescription = kCurrentSession;
    return self;
}
//其他两个回调做同样的修改就好    
void onProgress(final int id, final long downloadBytes, final long downloadNow, final long downloadTotal) {
        DownloadTask task = (DownloadTask)_taskMap.get(id);
        if (null != task) {
            task.bytesReceived = downloadBytes;
            task.totalBytesReceived = downloadNow;
            task.totalBytesExpected = downloadTotal;
        }
        if (_callBackInMainThread){
            Cocos2dxHelper.getActivity().runOnGLThread(new Runnable() {
                @Override
                public void run() {
                    nativeOnProgress(_id, id, downloadBytes, downloadNow, downloadTotal);
                }
            });
        }else {
//在子线程中回调
            new Runnable() {
                @Override
                public void run() {
                    nativeOnProgress(_id, id, downloadBytes, downloadNow, downloadTotal);
                }
            }.run();
        }
    }
//cv是getfiledata中使用的条件变量    
_downloader->onFileTaskSuccess = [this, &cv](const cocos2d::network::DownloadTask& task)
    {
//做一些游戏自己的检测逻辑,确认文件下载完成之后这里设置条件变量并且通知主线程恢复
            isDownloadOK = true;
            cv.notify_all();
    };
   

 

 


posted on 2024-01-03 18:24  二二的路人甲  阅读(45)  评论(0编辑  收藏  举报