赞 | 8 |
VIP | 0 |
好人卡 | 0 |
积分 | 49 |
经验 | 0 |
最后登录 | 2024-3-22 |
在线时间 | 445 小时 |
Lv3.寻梦者
- 梦石
- 0
- 星屑
- 4929
- 在线时间
- 445 小时
- 注册时间
- 2011-3-26
- 帖子
- 101
|
回帖奖励 +10 星屑
本帖最后由 rfvtgbzxc 于 2022-11-8 14:07 编辑
结论:可行,部分内容已自己实现过,部分内容有待实践。最终结果和你的问题的目标略有出入,即玩家还是必须要有最初的index.html,但是其他文件都可以放在数据包里。
方案:
1.利用IndexedDB作为存储方案
2.利用jszip直接管理读入的数据包
3.重写所有相关的访问api,改走jszip
详解:
1.浏览器这边没有读写用户文件系统的api,因此下载的zip不能像其他客户端程序那样被直接解压并放在文件系统里。但是浏览器是有让大文件持久化存储的api的——IndexedDB。MZ处理浏览器端存档的方案localforage就是使用了IndexedDB,理论上整个硬盘的空间都能用于IndexedDB存储,500MB的游戏不在话下。直接复用系统自带的localforage库即可轻松完成对IndexedDB的读写操作(直接用IndexedDB的api还是挺麻烦的)。但是单项Item似乎有大小限制,一个文件好像不能超过20+Mb,如果是Blob存储方式会大很多,我当时碰到存储限制后,把数据改用Blob存储了,就没有碰到超出的问题,不知道更大,大到500mb的一整个文件都放在条目里会不会有问题。但是这个问题不算大,大不了手动分块。所以整个游戏数据的存取就没有问题了。
2.现在读出了zip到内存中(以ArrayBuffer形式存在),要将其像平时打开zip文件那样使用它,我推荐使用jszip库。jszip库读取完这个zip后会生成一个像文件系统的对象,可以很容易获取里面的文件夹和文件,于是内部的文件也可以很容易被获取到。在没有压缩和加密的情况下,访问包内任意数据的速度基本上和从内存中访问源数据是一致的;有压缩的情况下,可能需要在下载数据后再多一步解压数据,再用无压缩的方式打包成压缩包才能保证运行速度。
这里有分歧,也可以不再压缩回去,而是直接用目录作为localforage的key进行存储和读取,这个方案的优劣有待讨论,如果localforage运行时有缓存差异就不大,没有的话,反复读取硬盘文件,性能可能会稍微差一点。
3.最后修改游戏内部读写文件的api,虽然要改的地方比较多,但是因为直接使用jszip的api,自己再封装一下promise请求,修改后的代码甚至可以比原来的更清爽,比如这是关于Data部分的存取代码:(其中Game.data就是一个jszip对象,包含了data目录下的所有内容)
- DataManager.loadDataFile = function (name, src) {
- Game.data.file(src + ".json")
- .async("string")
- .then(dataJson => {
- const obj = JSON.parse(dataJson);
- window[name] = obj;
- this.onLoad(obj);
- })
- .catch(e => {
- this.onDataFetchError(name, src);
- });
- };
复制代码 |
|