/** * Created by jsroads on 2019/10/29 . 1:35 下午 * Note: 此模块用于热更新工程清单文件的生成 * node 命令 例如 * node version_generator.js * */ var fs = require('fs'); var path = require('path'); var crypto = require('crypto');
let native = "native";//原生平台 let platform = "ios";//ios or android let gameName = "creatorHotUpDate";//develop or debug or release /** * develop 正在开发的版本 * debug 对内发布的测试版本 * release 对外发布的线上版本 * @type {string} */ let versionMode = "release";//develop or debug or release let version = "1.0.1";//版本号 let cdnDir = "http://172.16.28.99:8888"; let packageUrlList = [cdnDir,gameName,native,platform,versionMode]; let remoteManifestUrlList = [cdnDir,gameName,native,platform,versionMode,"project.manifest"]; let remoteVersionUrlList = [cdnDir,gameName,native,platform,versionMode,"version.manifest"]; var manifest = { packageUrl: packageUrlList.join("/"), remoteManifestUrl: remoteManifestUrlList.join("/"), remoteVersionUrl: remoteVersionUrlList.join("/"), version: version, assets: {}, searchPaths: [] };
//生成的manifest文件存放目录 var dest = 'assets/'; //项目构建后资源的目录 var src = 'build/jsb-link/';
/** *node version_generator.js -v 1.0.2 -u http://localhost:8888/你的游戏目录/ -s build/jsb-link/ -d assets/ */ // Parse arguments var i = 2; while ( i < process.argv.length) { var arg = process.argv[i];
if (needRestart) { this._am.setEventCallback(null); this._updateListener = null; // Prepend the manifest's search path var searchPaths = jsb.fileUtils.getSearchPaths(); var newPaths = this._am.getLocalManifest().getSearchPaths(); console.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); let list = this.info.version.split("."), currentVersion = 0; list.forEach((value, index, array) => { if (index < array.length - 1) { currentVersion += parseInt(value) * Math.pow(10, array.length - index) } }); console.log("new currentVersion:", JSON.stringify(currentVersion)); cc.sys.localStorage.setItem(GameHelper.currentVersion,JSON.stringify(currentVersion)); cc.audioEngine.stopAll(); cc.game.restart(); } }
// 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.infoLabel.string = "Verification passed : " + relativePath; returntrue; } else { this.infoLabel.string = "Verification passed : " + relativePath + ' (' + expectedMD5 + ')'; returntrue; } });
this.infoLabel.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(2); this.infoLabel.string = "Max concurrent tasks count have been limited to 2"; } this.fileProgress.progress = 0; this.byteProgress.progress = 0; }
privatecheck() { if (!cc.sys.isNative) { returnfalse; } this.storagePath = GameHelper.getStoragePath(); console.log('Storage path for remote asset : ' + this.storagePath);
// Init with empty manifest url for testing custom manifest this.assetsManager = new jsb.AssetsManager('', this.storagePath, (versionA: string, versionB: string) => { console.log("JS Custom Version Compare: version A is " + versionA + ' version B is ' + versionB); letvA: Array<string> = versionA.split('.'); letvB: Array<string> = versionB.split('.'); for (let i = 0; i < vA.length; ++i) { let a = parseInt(vA[i]); let b = parseInt(vB[i] || "0"); if (a === b) { continue; } else { return a - b; } } if (vB.length > vA.length) { return -1; } else { return0; } }); console.log('Hot update is ready please check or directly update.');
this.assetsManager.setEventCallback((event) => { cc.log('Code: ' + event.getEventCode()); switch (event.getEventCode()) { case jsb.EventAssetsManager.ERROR_NO_LOCAL_MANIFEST: console.log("No local manifest file found hot update skipped."); this.startGame(); break; case jsb.EventAssetsManager.ERROR_DOWNLOAD_MANIFEST: case jsb.EventAssetsManager.ERROR_PARSE_MANIFEST: console.log("Fail to download manifest file hot update skipped."); this.startGame(); break; case jsb.EventAssetsManager.ALREADY_UP_TO_DATE: console.log("Already up to date with the latest remote version."); this.startGame(); break; case jsb.EventAssetsManager.NEW_VERSION_FOUND: console.log('New version found please try to update.'); this.showHotUpDateDialog(); break; default: return; } }); if (this.assetsManager.getState() === jsb.AssetsManager.State.UNINITED) { // Resolve md5 url let url = this.manifestUrl.nativeUrl; console.log("=========================================="); console.log(url); if (cc.loader.md5Pipe) { url = cc.loader.md5Pipe.transformURL(url); } this.assetsManager.loadLocalManifest(url); //---------如果 版本号 倒数第二个更改了 清除缓存 小版本 才适合热更新 如果 自己不要要 可以注释这段 //-----------注释开始 // 之前版本保存在 local Storage 中的版本号,如果没有认为是旧版本 let previousVersion = parseFloat(cc.sys.localStorage.getItem(GameHelper.currentVersion)) || 0; let list = this.assetsManager.getLocalManifest().getVersion().split("."), currentVersion = 0; list.forEach((value, index, array) => { if (index < array.length - 1) { currentVersion += parseInt(value) * Math.pow(10, array.length - index) } }) console.log("previousVersion:", previousVersion); console.log("currentVersion:", currentVersion); if (previousVersion < currentVersion) { // 热更新的储存路径,如果旧版本中有多个,可能需要记录在列表中,全部清理 jsb.fileUtils.removeDirectory(this.storagePath); } //-----------注释结束 } if (!this.assetsManager.getLocalManifest() || !this.assetsManager.getLocalManifest().isLoaded()) { console.log('Failed to load local manifest ...'); return; } this.assetsManager.checkUpdate(); }
let versionMode = "release";//develop or debug or release let version = "1.0.2";//版本号 let cdnDir = "http://localhost:8888"; let packageUrlList = [cdnDir,gameName,native,platform,versionMode]; let remoteManifestUrlList = [cdnDir,gameName,native,platform,versionMode,"project.manifest"]; let remoteVersionUrlList = [cdnDir,gameName,native,platform,versionMode,"version.manifest"]; var manifest = { packageUrl: packageUrlList.join("/"), remoteManifestUrl: remoteManifestUrlList.join("/"), remoteVersionUrl: remoteVersionUrlList.join("/"), version: version, assets: {}, searchPaths: [] };
//生成的manifest文件存放目录 var dest = 'assets/'; //项目构建后资源的目录 var src = 'build/jsb-link/';
等待构建 OK 之后,然后 把 project.manifest 和 version.manifest 和 构建好的文件目录地址下
的res 和 src 文件夹 全部 复制到 我们的服务器 release 下
复制完成:
此时 再次修改我们的游戏内容,做出区分
修改我们的 版本号 为1.0.1
1 2 3 4 5 6 7 8 9 10 11 12 13 14
let versionMode = "release";//develop or debug or release let version = "1.0.1";//版本号 let cdnDir = "http://localhost:8888"; let packageUrlList = [cdnDir,gameName,native,platform,versionMode]; let remoteManifestUrlList = [cdnDir,gameName,native,platform,versionMode,"project.manifest"]; let remoteVersionUrlList = [cdnDir,gameName,native,platform,versionMode,"version.manifest"]; var manifest = { packageUrl: packageUrlList.join("/"), remoteManifestUrl: remoteManifestUrlList.join("/"), remoteVersionUrl: remoteVersionUrlList.join("/"), version: version, assets: {}, searchPaths: [] };
window.boot = function () { //-------------添加代码----开始--- if (cc && cc.sys.isNative) { var hotUpdateSearchPaths = cc.sys.localStorage.getItem('HotUpdateSearchPaths'); if (hotUpdateSearchPaths) { jsb.fileUtils.setSearchPaths(JSON.parse(hotUpdateSearchPaths)); console.log('[main.js] 热更新SearchPath: ' + JSON.parse(hotUpdateSearchPaths)); }else { console.log('[main.js] 未获取到热更新资源路径!'); } }else { console.log('[main.js] 不是native平台!'); } //-------------添加代码----结束--- var settings = window._CCSettings; window._CCSettings = undefined;
if ( !settings.debug ) { var uuids = settings.uuids;
var rawAssets = settings.rawAssets; var assetTypes = settings.assetTypes; var realRawAssets = settings.rawAssets = {}; for (var mount in rawAssets) { var entries = rawAssets[mount]; var realEntries = realRawAssets[mount] = {}; for (var id in entries) { var entry = entries[id]; var type = entry[1]; // retrieve minified raw asset if (typeof type === 'number') { entry[1] = assetTypes[type]; } // retrieve uuid realEntries[uuids[id] || id] = entry; } }
var scenes = settings.scenes; for (var i = 0; i < scenes.length; ++i) { var scene = scenes[i]; if (typeof scene.uuid === 'number') { scene.uuid = uuids[scene.uuid]; } }
var packedAssets = settings.packedAssets; for (var packId in packedAssets) { var packedIds = packedAssets[packId]; for (var j = 0; j < packedIds.length; ++j) { if (typeof packedIds[j] === 'number') { packedIds[j] = uuids[packedIds[j]]; } } }
var subpackages = settings.subpackages; for (var subId in subpackages) { var uuidArray = subpackages[subId].uuids; if (uuidArray) { for (var k = 0, l = uuidArray.length; k < l; k++) { if (typeof uuidArray[k] === 'number') { uuidArray[k] = uuids[uuidArray[k]]; } } } } }
functionsetLoadingDisplay () { // Loading splash scene var splash = document.getElementById('splash'); var progressBar = splash.querySelector('.progress-bar span'); cc.loader.onProgress = function (completedCount, totalCount, item) { var percent = 100 * completedCount / totalCount; if (progressBar) { progressBar.style.width = percent.toFixed(2) + '%'; } }; splash.style.display = 'block'; progressBar.style.width = '0%';
cc.director.once(cc.Director.EVENT_AFTER_SCENE_LAUNCH, function () { splash.style.display = 'none'; }); }
var onStart = function () { cc.loader.downloader._subpackages = settings.subpackages;
// Limit downloading max concurrent task to 2, // more tasks simultaneously may cause performance draw back on some android system / browsers. // You can adjust the number based on your own test result, you have to set it before any loading process to take effect. if (cc.sys.isBrowser && cc.sys.os === cc.sys.OS_ANDROID) { cc.macro.DOWNLOAD_MAX_CONCURRENT = 2; }
functionloadScene(launchScene) { cc.director.loadScene(launchScene, function (err) { if (!err) { if (cc.sys.isBrowser) { // show canvas var canvas = document.getElementById('GameCanvas'); canvas.style.visibility = ''; var div = document.getElementById('GameDiv'); if (div) { div.style.backgroundImage = ''; } } cc.loader.onProgress = null; console.log('Success to load scene: ' + launchScene); } elseif (CC_BUILD) { setTimeout(function () {
if (cc && cc.sys.isNative) { var hotUpdateSearchPaths = cc.sys.localStorage.getItem('HotUpdateSearchPaths'); if (hotUpdateSearchPaths) { jsb.fileUtils.setSearchPaths(JSON.parse(hotUpdateSearchPaths)); console.log('[main.js] 热更新SearchPath: ' + JSON.parse(hotUpdateSearchPaths)); }else { console.log('[main.js] 未获取到热更新资源路径!'); } }else { console.log('[main.js] 不是native平台!'); }