Cocos Creator 热更新文件MD5计算和需要注意的问题
Creator的热更新使用jsb。热更新基本按照 http://docs.cocos.com/creator/manual/zh/advanced-topics/hot-update.html?h=%E7%83%AD%E6%9B%B4%E6%96%B0这个官方教程,
以及https://github.com/cocos-creator/tutorial-hot-update这个官方示例就行。但是,有一些地方没有提及,这会导致热更出现的问题。
1.自己保存热更目录到localstorage,进入时先读取这个目录,然后设置成资源查找目录。
//1.在资源更新完毕后,重启的时候加入以下处理
var searchPaths = jsb.fileUtils.getSearchPaths();
var newPaths = this._am.getLocalManifest().getSearchPaths();
for(let i = 0;i<newPaths.length;i++){
if(searchPaths.indexOf(newPaths[i]) == -1){
Array.prototype.unshift(searchPaths, newPaths[i]);
}
}
jsb.fileUtils.setSearchPaths(searchPaths);
cc.sys.localStorage.setItem('HotUpdateSearchPaths', JSON.stringify(searchPaths)); //重启
var searchPaths = jsb.fileUtils.getSearchPaths();
var storePath = cc.sys.localStorage.getItem('HotUpdateSearchPaths');
storePath = JSON.parse(storePath);
storePath && jsb.fileUtils.setSearchPaths(storePath);
2.在热更模块中
md5 = crypto.createHash('md5').update(fs.readFileSync(subpath,"binary")).digest('hex');
这里fs.readFileSycn(subpath,"binary")返回的并非二进制类型,而是String。这会导致非文本文件md5计算错误。如果写入到manifest的文件md5是错误的,你下载文件后,
计算md5作比较当然就很难匹配上了。除此之外,我们在jsb里只能使用:
1.jsb.fileUtils.getStringFromFile(filePath);
2.jsb.fileUtils.getDataFromFile(filePath);
获取文件内容。getStringFromFile无法获取非文本文件内容。所以我们只能使用getDataFromFile获取文件二进制数据,它在js层面的视图类型是Uint8Array和nodejs readFileSync(subpath)一致。
3.前端js计算文件md5
1).改造version_generator.js
md5 = crypto.createHash('md5').update(fs.readFileSync(subpath,"binary")).digest('hex');
为
md5 = crypto.createHash('md5').update(fs.readFileSync(subpath)).digest('hex');
2)改造引擎自带的jsb_runtime_md5.js 它用js实现了byteArray md5的计算(大家可以在构建后搜索一下这文件,然后拷贝放到自己的js层工程里来)。但是这个还不能用,我们要稍微改造它。改造后的文件。
/**
* from jsb_runtime_md5.js
* @param {} data
*/
module.exports = function(data){
// for test/debug
function fflog(msg) {
try {
console.log(msg);
} catch(e) {}
} // convert number to (unsigned) 32 bit hex, zero filled string
function to_zerofilled_hex(n) {
var t1 = (n >>> 24).toString(16);
var t2 = (n & 0x00FFFFFF).toString(16);
return "00".substr(0, 2 - t1.length) + t1 +
"000000".substr(0, 6 - t2.length) + t2;
} // convert a 64 bit unsigned number to array of bytes. Little endian
function int64_to_bytes(num) {
var retval = [];
for (var i = 0; i < 8; i++) {
retval.push(num & 0xFF);
num = num >>> 8;
}
return retval;
} // 32 bit left-rotation
function rol(num, places) {
return ((num << places) & 0xFFFFFFFF) | (num >>> (32 - places));
} // The 4 MD5 functions
function fF(b, c, d) {
return (b & c) | (~b & d);
} function fG(b, c, d) {
return (d & b) | (~d & c);
} function fH(b, c, d) {
return b ^ c ^ d;
} function fI(b, c, d) {
return c ^ (b | ~d);
} // pick 4 bytes at specified offset. Little-endian is assumed
function bytes_to_int32(arr, off) {
return (arr[off + 3] << 24) | (arr[off + 2] << 16) | (arr[off + 1] << 8) | (arr[off]);
}
// convert the 4 32-bit buffers to a 128 bit hex string. (Little-endian is assumed)
function int128le_to_hex(a, b, c, d) {
var ra = "";
var t = 0;
var ta = 0;
for (var i = 3; i >= 0; i--) {
ta = arguments[i];
t = (ta & 0xFF);
ta = ta >>> 8;
t = t << 8;
t = t | (ta & 0xFF);
ta = ta >>> 8;
t = t << 8;
t = t | (ta & 0xFF);
ta = ta >>> 8;
t = t << 8;
t = t | ta;
ra = ra + to_zerofilled_hex(t);
}
return ra;
} // check input data type and perform conversions if needed if (!data instanceof Uint8Array){
fflog("input data type mismatch only support Uint8Array");
return null;
}
var databytes = [];
for(var i = 0; i < data.byteLength;i++){
databytes.push(data[i]);
} // save original length
var org_len = databytes.length; // first append the "1" + 7x "0"
databytes.push(0x80); // determine required amount of padding
var tail = databytes.length % 64;
// no room for msg length?
if (tail > 56) {
// pad to next 512 bit block
for (var i = 0; i < (64 - tail); i++) {
databytes.push(0x0);
}
tail = databytes.length % 64;
}
for (i = 0; i < (56 - tail); i++) {
databytes.push(0x0);
}
// message length in bits mod 512 should now be 448
// append 64 bit, little-endian original msg length (in *bits*!)
databytes = databytes.concat(int64_to_bytes(org_len * 8)); // initialize 4x32 bit state
var h0 = 0x67452301;
var h1 = 0xEFCDAB89;
var h2 = 0x98BADCFE;
var h3 = 0x10325476; // temp buffers
var a = 0,
b = 0,
c = 0,
d = 0; function _add(n1, n2) {
return 0x0FFFFFFFF & (n1 + n2)
} // function update partial state for each run
var updateRun = function(nf, sin32, dw32, b32) {
var temp = d;
d = c;
c = b;
//b = b + rol(a + (nf + (sin32 + dw32)), b32);
b = _add(b,
rol(
_add(a,
_add(nf, _add(sin32, dw32))
), b32
)
);
a = temp;
}; // Digest message
for (i = 0; i < databytes.length / 64; i++) {
// initialize run
a = h0;
b = h1;
c = h2;
d = h3; var ptr = i * 64; // do 64 runs
updateRun(fF(b, c, d), 0xd76aa478, bytes_to_int32(databytes, ptr), 7);
updateRun(fF(b, c, d), 0xe8c7b756, bytes_to_int32(databytes, ptr + 4), 12);
updateRun(fF(b, c, d), 0x242070db, bytes_to_int32(databytes, ptr + 8), 17);
updateRun(fF(b, c, d), 0xc1bdceee, bytes_to_int32(databytes, ptr + 12), 22);
updateRun(fF(b, c, d), 0xf57c0faf, bytes_to_int32(databytes, ptr + 16), 7);
updateRun(fF(b, c, d), 0x4787c62a, bytes_to_int32(databytes, ptr + 20), 12);
updateRun(fF(b, c, d), 0xa8304613, bytes_to_int32(databytes, ptr + 24), 17);
updateRun(fF(b, c, d), 0xfd469501, bytes_to_int32(databytes, ptr + 28), 22);
updateRun(fF(b, c, d), 0x698098d8, bytes_to_int32(databytes, ptr + 32), 7);
updateRun(fF(b, c, d), 0x8b44f7af, bytes_to_int32(databytes, ptr + 36), 12);
updateRun(fF(b, c, d), 0xffff5bb1, bytes_to_int32(databytes, ptr + 40), 17);
updateRun(fF(b, c, d), 0x895cd7be, bytes_to_int32(databytes, ptr + 44), 22);
updateRun(fF(b, c, d), 0x6b901122, bytes_to_int32(databytes, ptr + 48), 7);
updateRun(fF(b, c, d), 0xfd987193, bytes_to_int32(databytes, ptr + 52), 12);
updateRun(fF(b, c, d), 0xa679438e, bytes_to_int32(databytes, ptr + 56), 17);
updateRun(fF(b, c, d), 0x49b40821, bytes_to_int32(databytes, ptr + 60), 22);
updateRun(fG(b, c, d), 0xf61e2562, bytes_to_int32(databytes, ptr + 4), 5);
updateRun(fG(b, c, d), 0xc040b340, bytes_to_int32(databytes, ptr + 24), 9);
updateRun(fG(b, c, d), 0x265e5a51, bytes_to_int32(databytes, ptr + 44), 14);
updateRun(fG(b, c, d), 0xe9b6c7aa, bytes_to_int32(databytes, ptr), 20);
updateRun(fG(b, c, d), 0xd62f105d, bytes_to_int32(databytes, ptr + 20), 5);
updateRun(fG(b, c, d), 0x2441453, bytes_to_int32(databytes, ptr + 40), 9);
updateRun(fG(b, c, d), 0xd8a1e681, bytes_to_int32(databytes, ptr + 60), 14);
updateRun(fG(b, c, d), 0xe7d3fbc8, bytes_to_int32(databytes, ptr + 16), 20);
updateRun(fG(b, c, d), 0x21e1cde6, bytes_to_int32(databytes, ptr + 36), 5);
updateRun(fG(b, c, d), 0xc33707d6, bytes_to_int32(databytes, ptr + 56), 9);
updateRun(fG(b, c, d), 0xf4d50d87, bytes_to_int32(databytes, ptr + 12), 14);
updateRun(fG(b, c, d), 0x455a14ed, bytes_to_int32(databytes, ptr + 32), 20);
updateRun(fG(b, c, d), 0xa9e3e905, bytes_to_int32(databytes, ptr + 52), 5);
updateRun(fG(b, c, d), 0xfcefa3f8, bytes_to_int32(databytes, ptr + 8), 9);
updateRun(fG(b, c, d), 0x676f02d9, bytes_to_int32(databytes, ptr + 28), 14);
updateRun(fG(b, c, d), 0x8d2a4c8a, bytes_to_int32(databytes, ptr + 48), 20);
updateRun(fH(b, c, d), 0xfffa3942, bytes_to_int32(databytes, ptr + 20), 4);
updateRun(fH(b, c, d), 0x8771f681, bytes_to_int32(databytes, ptr + 32), 11);
updateRun(fH(b, c, d), 0x6d9d6122, bytes_to_int32(databytes, ptr + 44), 16);
updateRun(fH(b, c, d), 0xfde5380c, bytes_to_int32(databytes, ptr + 56), 23);
updateRun(fH(b, c, d), 0xa4beea44, bytes_to_int32(databytes, ptr + 4), 4);
updateRun(fH(b, c, d), 0x4bdecfa9, bytes_to_int32(databytes, ptr + 16), 11);
updateRun(fH(b, c, d), 0xf6bb4b60, bytes_to_int32(databytes, ptr + 28), 16);
updateRun(fH(b, c, d), 0xbebfbc70, bytes_to_int32(databytes, ptr + 40), 23);
updateRun(fH(b, c, d), 0x289b7ec6, bytes_to_int32(databytes, ptr + 52), 4);
updateRun(fH(b, c, d), 0xeaa127fa, bytes_to_int32(databytes, ptr), 11);
updateRun(fH(b, c, d), 0xd4ef3085, bytes_to_int32(databytes, ptr + 12), 16);
updateRun(fH(b, c, d), 0x4881d05, bytes_to_int32(databytes, ptr + 24), 23);
updateRun(fH(b, c, d), 0xd9d4d039, bytes_to_int32(databytes, ptr + 36), 4);
updateRun(fH(b, c, d), 0xe6db99e5, bytes_to_int32(databytes, ptr + 48), 11);
updateRun(fH(b, c, d), 0x1fa27cf8, bytes_to_int32(databytes, ptr + 60), 16);
updateRun(fH(b, c, d), 0xc4ac5665, bytes_to_int32(databytes, ptr + 8), 23);
updateRun(fI(b, c, d), 0xf4292244, bytes_to_int32(databytes, ptr), 6);
updateRun(fI(b, c, d), 0x432aff97, bytes_to_int32(databytes, ptr + 28), 10);
updateRun(fI(b, c, d), 0xab9423a7, bytes_to_int32(databytes, ptr + 56), 15);
updateRun(fI(b, c, d), 0xfc93a039, bytes_to_int32(databytes, ptr + 20), 21);
updateRun(fI(b, c, d), 0x655b59c3, bytes_to_int32(databytes, ptr + 48), 6);
updateRun(fI(b, c, d), 0x8f0ccc92, bytes_to_int32(databytes, ptr + 12), 10);
updateRun(fI(b, c, d), 0xffeff47d, bytes_to_int32(databytes, ptr + 40), 15);
updateRun(fI(b, c, d), 0x85845dd1, bytes_to_int32(databytes, ptr + 4), 21);
updateRun(fI(b, c, d), 0x6fa87e4f, bytes_to_int32(databytes, ptr + 32), 6);
updateRun(fI(b, c, d), 0xfe2ce6e0, bytes_to_int32(databytes, ptr + 60), 10);
updateRun(fI(b, c, d), 0xa3014314, bytes_to_int32(databytes, ptr + 24), 15);
updateRun(fI(b, c, d), 0x4e0811a1, bytes_to_int32(databytes, ptr + 52), 21);
updateRun(fI(b, c, d), 0xf7537e82, bytes_to_int32(databytes, ptr + 16), 6);
updateRun(fI(b, c, d), 0xbd3af235, bytes_to_int32(databytes, ptr + 44), 10);
updateRun(fI(b, c, d), 0x2ad7d2bb, bytes_to_int32(databytes, ptr + 8), 15);
updateRun(fI(b, c, d), 0xeb86d391, bytes_to_int32(databytes, ptr + 36), 21); // update buffers
h0 = _add(h0, a);
h1 = _add(h1, b);
h2 = _add(h2, c);
h3 = _add(h3, d);
}
// Done! Convert buffers to 128 bit (LE)
return int128le_to_hex(h3, h2, h1, h0).toLowerCase();
};
这里我把它改造成了只接受Uint8Array数据的格式。它原先只能计算字符串的md5码。
3)脚本里的使用方式
//引入我们的md5模块
const MD5 = require("jsb_runtime_md5");
/**
* 指定文件验证函数
* @param path 下载的文件的本地路径
* @param asset 下载的资源
*/
_verifyFileHandle:function(path, asset){
//服务器上manifest里对该项资源配置的Md5码
//asset.md5
//服务器端的相对路径
//asset.path
//是否为压缩文件
//asset.compressed
//文件尺寸
//asset.size
//下载状态 包含 UNSTARTED、DOWNLOADING、SUCCESSED、UNMARKED
//asset.downloadState
var resMD5 = this.calMD5OfFile(path);
return asset.md5 == resMD5;
}, calMD5OfFile:function(filePath){return MD5(jsb.fileUtils.getDataFromFile(filePath));}
Cocos Creator 热更新文件MD5计算和需要注意的问题的更多相关文章
- cocos creator热更新教程
1.下载HotUpdate热更新DEMO 2.在cocos creator中下载热更新插件,cocos creator版本要在1.7及以上版本 3.插件默认安装在C:\Users\Administra ...
- (原创)cocos lua 热更新从零开始(一)最简单demo
开发环境:WIN7 + cocos2dx 3.10 lua版本 0.学习这篇内容的基础是你要会创建并运行一个cocos lua项目 1.热更新的思想所谓的热更新,就是在线更新代码和资源.热更新的过程首 ...
- Unity热更新文件的服务器部署(IIS)
1.VS新建一个"ASP.NET空网站" 工程结构如下 最好设置.Net FrameWork版本为 V4.0或者V4.5版本的,因为我们的程序最后是要部署到阿里云的虚拟服务器上的, ...
- 【Quick 3.3】资源脚本加密及热更新(三)热更新模块
[Quick 3.3]资源脚本加密及热更新(三)热更新模块 注:本文基于Quick-cocos2dx-3.3版本编写 一.介绍 lua相对于c++开发的优点之一是代码可以在运行的时候才加载,基于此我们 ...
- Cocos2d-js 热更新学习笔记
转载至: http://blog.csdn.net/pt_xxj/article/details/68927705 为什么还要再写一篇关于cocos2d js热更新的笔记,最单纯的想法就是记录心得,另 ...
- 【转】: 《江湖X》开发笔谈 - 热更新框架
前言 大家好,我们这期继续借着我们工作室正在运营的在线游戏<江湖X>来谈一下热更新机制以及我们的理解和解决方案.这里先简单的介绍一下热更新的概念,熟悉这部分的朋友可以跳过,直接看我们的方案 ...
- Cocos Creator—定制H5游戏首页loading界面
Cocos Creator从1.0版本发布到现在也有一年多了,按理说一些常见的问题网上都有解决方案,例如"如何自定义首页加载进度条界面"这种普遍需求,应该所有人都会遇到的,因此也有 ...
- nodejs五子棋online游戏开发视频教程,客户端cocos creator js
开发的游戏是五子棋online,网络版的,服务端部分和客户端部分都在这个教程里面,可以看一下目录! 服务器nodejs游戏开发教程 使用Nodejs开发网络服务器 游戏服务端 ,cocos creat ...
- ionic cordova 热更新(引用自www.zyyapp.com/post/116.html)
上篇文章cordova 把html打包成安卓应用 http://www.zyyapp.com/post/115.html cordova 热更新是一个大坑,我看了一天一夜才明白.网上的教程都没说到重点 ...
随机推荐
- 面向对象编程(oop)的变迁
作者:匿名用户链接:https://www.zhihu.com/question/34018003/answer/132740170来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请 ...
- Java多线程(2):线程加入/join()
线程加入 join()方法,等待其他线程终止.在当前线程(主线程)中调用另一个线程(子线程)的join()方法,则当前线程转入阻塞状态,直到另一个线程运行结束,当前线程再由阻塞转为就绪状态. 也就是主 ...
- 解决 nw 报错 net::ERR_UNSAFE_PORT
今天 nw 应用里面的前端请求突然不发送了,也没有异常的信息,后来换上开发版 nw 立刻就发现了报错: net::ERR_UNSAFE_PORT 这个错误的意思很明显,就是请求的 http 端 ...
- Golang 单例模式 singleton pattern
在Java中,单例模式的实现主要依靠类中的静态字段.在Go语言中,没有静态类成员,所以我们使用的包访问机制和函数来提供类似的功能.来看下下面的例子: package singleton ...
- UOJ#494K点最短路
#include <cstdio> #include <iostream> #include <cstring> #include <queue> #d ...
- Ciso三层交换 上vlan间互通, 端口映射到vlan
路由器2911配置: !hostname router interface GigabitEthernet0/0 ip address 10.0.0.2 255.0.0.0 ip nat outsid ...
- 如何将其它javaweb项目变成可以成功在自己eclipse环境中运行的javaweb项目?
说明:此文档仅适用于以下两种情况 (1)myeclipse项目需要在eclipse环境中运行 (2)eclipse项目,但是无法在自己的电脑eclipse环境中运行 注意:以下 ...
- TensorFlow实战第五课(MNIST手写数据集识别)
Tensorflow实现softmax regression识别手写数字 MNIST手写数字识别可以形象的描述为机器学习领域中的hello world. MNIST是一个非常简单的机器视觉数据集.它由 ...
- 【机器学习】深入理解拉格朗日乘子法(Lagrange Multiplier) 和KKT条件
在求取有约束条件的优化问题时,拉格朗日乘子法(Lagrange Multiplier) 和KKT条件是非常重要的两个求取方法,对于等式约束的优化问题,可以应用拉格朗日乘子法去求取最优值:如果含有不等式 ...
- 通达信金融终端_尘缘整合_V7.12
http://pan.baidu.com/s/1gvtPO http://pan.baidu.com/s/1xqrk6 通达信金融终端_尘缘整合_V7.12