123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401 |
- const {ccclass, property} = cc._decorator;
- /**
- * 热更新
- */
- @ccclass
- export default class HotUpdate extends cc.Component {
-
- @property(cc.Asset)
- public manifestUrl:cc.Asset = null;
- @property(cc.Node)
- public gxNode:cc.Node = null;//更新load
- // @property(cc.Label)
- // public mInfo:cc.Label = null;
- @property(cc.Node)
- public mMyNode:cc.Node = null;
- @property(cc.Label)
- public mV1:cc.Label = null;
- @property(cc.Label)
- public mV2:cc.Label = null;
- @property(cc.Label)
- public mLoadBfb:cc.Label = null;
- @property(cc.Label)
- public fileCount:cc.Label = null;//文件数量
- @property(cc.ProgressBar)
- public byteProgress:cc.ProgressBar = null;//下载进度
- // @property(cc.Node)
- // mLogContent:cc.Node = null;//更新日志
- private _updating:boolean = false;
- private _am:jsb.AssetsManager = null;//jsb.AssetsManager
- private _canRetry:boolean = false;//是否可以重新下载
- private _storagePath:string;//存储路径
- private versionCompareHandle: (versionA: string, versionB: string) => number = null!;
- public login(){
- if(cc.sys.isNative){
- // cc.director.loadScene('anysdkLogin');
- cc.director.loadScene('main');
- }else{
- cc.director.loadScene('main');
- }
- }
- public exitGame(){
- cc.game.end();
- }
- public onLoad(){
- let proto = cc.ProgressBar.prototype;
- let updateBarStatus = proto['_updateBarStatus'];
- proto['_updateBarStatus'] = function () {
- if (this.progress == 0) {
- this.progress = 0.001;
- }
- updateBarStatus.bind(this)();
- }
- this.mV1.node.active = false
- this.mV2.node.active = false
- cc.game.setFrameRate(35);
- this.gxNode.active = false;
- if (!cc.sys.isNative) {
- this.login();
- return;
- }
- this._storagePath = ((jsb.fileUtils ? jsb.fileUtils.getWritablePath() : '/') + 'mmtg-remote-asset');
- cc.log('Storage path for remote asset : ' + this._storagePath);
- let myself = this;
- this.versionCompareHandle = function (versionA: string, versionB: string) {
- console.log("JS Custom Version Compare: version A is " + versionA + ', version B is ' + versionB);
- myself.mV1.node.active = true
- myself.mV2.node.active = true
- myself.mV1.string = '客户端版本:'+versionA
- myself.mV2.string = '服务器版本:'+versionB
- var vA = versionA.split('.');
- var vB = versionB.split('.');
- for (var i = 0; i < vA.length; ++i) {
- var a = parseInt(vA[i]);
- var b = parseInt(vB[i] || '0');
- if (a === b) {
- continue;
- }
- else {
- return a - b;
- }
- }
- if (vB.length > vA.length) {
- return -1;
- }
- else {
- return 0;
- }
- };
- // Init with empty manifest url for testing custom manifest
- this._am = new jsb.AssetsManager('', this._storagePath, this.versionCompareHandle);
- // Setup the verification callback, but we don't have md5 check function yet, so only print some message
- // Return true if the verification passed, otherwise return false
-
- this._am.setVerifyCallback((path, asset)=> {
- // When asset is compressed, we don't need to check its md5, because zip file have been deleted.
- var compressed = asset.compressed;
- // Retrieve the correct md5 value.
- var expectedMD5 = asset.md5;
- // asset.path is relative path and path is absolute.
- var relativePath = asset.path;
- // The size of asset file, but this value could be absent.
- var size = asset.size;
- if (compressed) {
- // this.mInfo.string = "Verification passed : " + relativePath;
- return true;
- }else {
- // this.mInfo.string = "Verification passed : " + relativePath + ' (' + expectedMD5 + ')';
- // if(!jsb.fileUtils.isFileExist(path)){
- // return false;
- // }
- // let dataBinary = jsb.fileUtils.getDataFromFile(path);
- // let buffer = nodeJsBufferTool.from(dataBinary);
- // let md5Code = crypto.createHash('md5').update(buffer).digest('hex');
- // if(md5Code !== asset.md5){
- // cc.log('不一致文件:',path);
- // cc.log('md5Code = ',md5Code);
- // cc.log('asset = ',asset.md5);
- // // cc.log('dataBinary : ',dataBinary);
- // // cc.log('strData : ',strData);
- // return false;
- // }
- // cc.log('一致文件 :',path);
- // return true;
- // this.mInfo.string = "Verification passed : " + relativePath + ' (' + expectedMD5 + ')';
- if(!jsb.fileUtils.isFileExist(path)){
- return false;
- }
- let fileSize = jsb.fileUtils.getFileSize(path);
-
- if(fileSize != asset.size){
- return false;
- }
- return true;
- }
- });
- // this.mInfo.string = 'Hot update is ready, please check or directly update.';
- if (cc.sys.os === cc.sys.OS_ANDROID) {
- // Some Android device may slow down the download process when concurrent tasks is too much.
- // The value may not be accurate, please do more test and find what's most suitable for your game.
- this._am.setMaxConcurrentTask(10);
- // this.mInfo.string = "Max concurrent tasks count have been limited to 2";
- }else{
- this._am.setMaxConcurrentTask(15);
- }
-
- this.fileCount.string = '';
- this.mLoadBfb.string = '';
- this.byteProgress.progress = 0;
- //判断是否需要下载新包更新
- //1.获取app版本
- //2.获取服务器最新版本
- //3.打开下载页
- // if (cc.sys.os === cc.sys.OS_ANDROID) {
- // this.getServerAppVersion((v1)=>{
- // if(v1){
- // let v2 = this.getAppVersion();
- // let state = this.versionCompareHandle(v1,v2);
- // if(state > 0){
- // //如果有新版本
- // this.updateBtn.active = true;
- // }else{
- // this.checkUpdate();
- // }
- // }else{
- // this.checkUpdate();
- // }
- // });
- // }else{
- // this.checkUpdate();
- // }
- this.checkUpdate();
- }
- public checkUpdate() {
- if (this._updating) {
- // cc.log('Checking or updating ...');
- this.pushLog('Checking or updating ...');
- return;
- }
- if (this._am.getState() === jsb.AssetsManager.State.UNINITED) {
- var url = this.manifestUrl.nativeUrl;
- this._am.loadLocalManifest(url);
- }
- if (!this._am.getLocalManifest() || !this._am.getLocalManifest().isLoaded()) {
- // cc.log('Failed to load local manifest ...');
- this.pushLog('Failed to load local manifest ...');
- return;
- }
- this._am.setEventCallback(this.checkCb.bind(this));
- this._am.checkUpdate();
- this._updating = true;
- }
- public hotUpdate () {
- this.gxNode.active = true;
- this.fileCount.string = 'loading...';
- if (this._am && !this._updating) {
- this._am.setEventCallback(this.updateCb.bind(this));
- if (this._am.getState() === jsb.AssetsManager.State.UNINITED) {
- // Resolve md5 url
- var url = this.manifestUrl;
- if (cc.loader.md5Pipe) {
- url = cc.loader.md5Pipe.transformURL(url);
- }
- this._am.loadLocalManifest(url);
- }
- this._am.update();
- this._updating = true;
- }
- }
- public checkCb(event){
- cc.log('Code: ' + event.getEventCode());
- switch (event.getEventCode())
- {
- case jsb.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST:
- cc.log("No local manifest file found, hot update skipped.");
- this.login();
- break;
- case jsb.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST:
- case jsb.EventAssetsManager.ERROR_PARSE_MANIFEST:
- cc.log("Fail to download manifest file, hot update skipped.");
- this.login();
- break;
- case jsb.EventAssetsManager.ALREADY_UP_TO_DATE:
- cc.log("Already up to date with the latest remote version.");
- this.login();
- break;
- case jsb.EventAssetsManager.NEW_VERSION_FOUND:
- cc.log("New version found, please try to update.");
- // this.panel.fileProgress.progress = 0;
- // this.panel.byteProgress.progress = 0;
- // this.updateBtn.active = true;
- // cc.log('getTotalBytes : ',event.getTotalBytes());
- this._am.setEventCallback(null);
- this._updating = false;
- this.hotUpdate();
- break;
- default:
- return;
- }
- }
- public updateCb(event) {
- var needRestart = false;
- var failed = false;
- switch (event.getEventCode())
- {
- case jsb.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST:
- cc.log('No local manifest file found, hot update skipped.');
- failed = true;
- break;
- case jsb.EventAssetsManager.UPDATE_PROGRESSION:
- // this.byteProgress.progress = event.getPercent();
- let percentByFile = event.getPercentByFile();
- if(!percentByFile){
- percentByFile = 0;
- }else{
- if(event.getDownloadedFiles() < event.getTotalFiles()-1){
- this.fileCount.string = event.getDownloadedFiles() + ' / ' + event.getTotalFiles();
- }else{
- this.fileCount.string = '文件解压中...';
- }
- }
- this.byteProgress.progress = percentByFile;
- this.mMyNode.x = 915*percentByFile
- // if(event.getPercent()){
- // this.mLoadBfb.string = Math.floor(event.getPercentByFile()*100)+'%';
- // }
- // this.mLoadBfb.string = Math.floor(percentByFile*100)+'%';
- // var msg = event.getMessage();
- // if (msg) {
- // // this.panel.info.string = 'Updated file: ' + msg;
- // cc.log(event.getPercent()/100 + '% : ' + msg);
- // }
-
- break;
- case jsb.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST:
- case jsb.EventAssetsManager.ERROR_PARSE_MANIFEST:
- cc.log('Fail to download manifest file, hot update skipped.');
- failed = true;
- break;
- case jsb.EventAssetsManager.ALREADY_UP_TO_DATE:
- cc.log('Already up to date with the latest remote version.');
- failed = true;
- break;
- case jsb.EventAssetsManager.UPDATE_FINISHED:
- this.pushLog('Update finished. ' + event.getMessage());
- needRestart = true;
- break;
- case jsb.EventAssetsManager.UPDATE_FAILED:
- this.pushLog('Update failed. ' + event.getMessage());
- // this.mInfo.string = '更新失败,是否重试?';
- this._updating = false;
- this._canRetry = true;
- this.retry();
- // this.updateBtn.active = true;
- // needRestart = true;
- // this.hotUpdate();
- break;
- case jsb.EventAssetsManager.ERROR_UPDATING:
- this.pushLog('Asset update error: ' + event.getAssetId() + ', ' + event.getMessage());
- // needRestart = true;
- // this.hotUpdate();
- break;
- case jsb.EventAssetsManager.ERROR_DECOMPRESS:
- cc.log(event.getMessage());
- needRestart = true;
- break;
- default:
- break;
- }
- if (failed) {
- this._am.setEventCallback(null);
- this._updating = false;
- this.login();
- }
- if (needRestart) {
- this._am.setEventCallback(null);
- // Prepend the manifest's search path
- var searchPaths = jsb.fileUtils.getSearchPaths();
- var newPaths = this._am.getLocalManifest().getSearchPaths();
- cc.log(JSON.stringify(newPaths));
- Array.prototype.unshift.apply(searchPaths, newPaths);
- // This value will be retrieved and appended to the default search path during game startup,
- // please refer to samples/js-tests/main.js for detailed usage.
- // !!! Re-add the search paths in main.js is very important, otherwise, new scripts won't take effect.
- cc.sys.localStorage.setItem('HotUpdateSearchPaths', JSON.stringify(searchPaths));
- jsb.fileUtils.setSearchPaths(searchPaths);
- cc.audioEngine.stopAll();
- setTimeout(() => {
- cc.game.restart();
- }, 1000)
-
- }
- }
- // public loadCustomManifest() {
- // if (this._am.getState() === jsb.AssetsManager.State.UNINITED) {
- // var manifest = new jsb.Manifest(customManifestStr, this._storagePath);
- // this._am.loadLocalManifest(manifest, this._storagePath);
- // this.panel.info.string = 'Using custom manifest';
- // }
- // }
-
- public retry(){
- if (!this._updating && this._canRetry) {
- this._canRetry = false;
-
- // cc.log('Retry failed Assets...');
- this.pushLog('Retry failed Assets...');
- this._am.downloadFailedAssets();
- }
- }
- public onDestroy () {
- if (this._am) {
- this._am.setEventCallback(null);
- }
- }
- public pushLog(msg){
- // let node = new cc.Node();
- // node.anchorX = 0;
- // node.height = 32;
- // node.color = cc.color(0,0,0);
- // let log = node.addComponent(cc.Label)
- // log.overflow = cc.Label.Overflow.RESIZE_HEIGHT;
- // log.string = msg;
- // log.node.parent = this.mLogContent;
- }
- public onclickCancel(){
- this.checkUpdate();
- }
- }
|