经过初步测试,通过ipfs索引文件,在浏览器上玩ons游戏貌似是可行的,虽然还存在一些问题。
大致原理
- onsyuri的web版本可以通过文件索引和url懒加载游戏资源文件。
- ipfs可以通过网关加文件的cid获取文件
结合上面两点,能够有一种神奇的效果,将游戏的资源文件上传到ipfs,将每个文件的cid
写到onsyuri_index.json
内对应的url
上,就可以通过ipfs索引游戏文件,并且能够分布式的扩散到其他节点,能够自然的完成游戏的传播与分享。
前置条件
在开始之前先准备好以下东西:
- ipfs desktop
- onsyuri.wasm
- onsyuri.js
- onsyuri.html
- onsyuri_index.py
- 一个ons的游戏
前往ipfs的github发布页上下载对应系统的安装包并安装,windows的是exe结尾,具体使用可以在网上多搜索,这不是本文的重点,不详细说明。
onsyuri同理,发布页下载web版本之后解压,或者自行编译。
明确目标
网页运行的流程大概是,先在html文件里面加载了js胶水代码,js胶水代码加载了wasm文件,之后加载json索引文件,在游戏运行的时候通过索引加载游戏的资源文件。
我们要把这些移植到ipfs上,那就要把所有通过url获取文件的方式全部改成通过cid获取。
值得注意的是,cid是根据文件内容计算出来的,在生成cid之后就不要修改文件的内容,如果修改了文件那就要重新上传并使用新的cid,以及一定要注意修改的顺序。
修改html用get方式传入index.json
首先打开onsyuri.html
在文件开头找到
1 | <meta onsyuri_js="onsyuri.js"> |
这是通过在meta
设置文件名之后在这个位置
在这里确定的文件url。
因为每个游戏的index都不一样,如果为每个游戏都上传一个html,我认为是很没有必要的,所以我决定把这个变成一个通用的模拟器页面,通过get传参的方式传入index。我js不太会,以下是网上找的获取get参数的方法,如果有更好的方法也可以更改:
1 | function GetQueryString(name){ |
之后更改获取index的代码如下:
之后在进入模拟器页面时加上?index=onsyuri_index.json
或者自己的json的url即可。
修改js
onsyuri.js
文件主要是用来加载onsyuri.wasm
的,而wasm没有任何依赖,可以直接上传ipfs,然后复制cid
之后打开js,这个生成的胶水代码完全没有格式化,直接用查找替换将onsyuri.wasm
替换成上面的cid
这时候这个胶水文件就完成了,可以上传了
最终修改html
胶水代码的url也是在meta
里面设置的,修改为cid
1 | <meta onsyuri_js="QmQq3UxfKDBsD5gGMy3NK7yZFEjSmxPG2KaxPKKH3imHFF"> |
这时候,html和js和wasm已经完全耦合在一起了,除了html,修改其中任何一个文件,都要按照上面的顺序修改并重新上传这3个文件,如果要修改,请确保自己神志清醒,知道自己在干什么。
游戏文件上传和生成索引
建议拆包并开启懒加载,以获取最佳体验。不过应该是我多虑了,游戏资源拆包之后可能会生成上万个文件,大多是语音和序列帧动画等数量极多的文件,不知道ipfs能够索引的最大文件数量是多大,不过这么长的哈希,应该是不会冲突了吧即使我上传100G大合集应该也不会吧。
拆包需要自行编译nsadec或者用其他软件拆包,这里不多介绍。计算cid的方法,我也不太懂哈希,之前调库瞎搞搞了一晚上都没算出跟上传的一样的,所以不要管怎么计算cid了,从调库变成系统调用ipfs
,如果是使用的ipfs desktop,在设置勾上“控制台”
修改onsyuri_index.py
,注意,以下并非规范操作,且不知道会有什么其他影响,谨慎使用
1 | def make_filelist(inpath, urlbase): |
path的必须要用引号包围,有一些文件命名不规范,名字里面带有空格。
-n
的参数是不上传只计算哈希,如果要顺便上传就去掉-n
,只保留-q
。
[:-1]
是去掉行末换行。
最后使用ipfs add
上传游戏文件和onsyuri_index.json
就完成了,记得记下onsyuri_index.json
的cid。
测试使用
ipfs公共网关(如https://ipfs.io
)都位于国外,因为一些网络原因,我们的节点一般是不能和公共网关连接的,所以我们的游戏资源可能无法同步到公共网关(其实也可以,但是需要很久),所以最好使用自己节点的网关来访问。使用方法为:
1 | (ipfs网关)/ipfs/(onsyuri.html的cid)?index=(对应游戏的onsyuri_index.json的cid) |
用我自己的举个例子:
- 本地ipfs网关为
127.0.0.1:8080
- onsyuri.html的cid为
QmX6UfTaWxiKfaPh9PQ59ExACboGr9TUvCs3pVtMcExsJj
- 游戏的onsyuri_index.json的cid为
Qmf9rq18AMbgsBiCwmrCNxxsnbsk3BLBwT47i3h1UfC6UR
那这个使用的链接应为
1 | http://127.0.0.1:8080/ipfs/QmX6UfTaWxiKfaPh9PQ59ExACboGr9TUvCs3pVtMcExsJj?index=Qmf9rq18AMbgsBiCwmrCNxxsnbsk3BLBwT47i3h1UfC6UR |
效果如下:
用公共网关也可以但是卡得几乎不能玩
如果要分享给别人玩,目前没有什么好的方法,只能让对方也装上ipfs desktop,使用自己的节点来访问,国内节点之间连接的速度还是可以接受的。
如果将来使用这种方式的人多了,资源终于缓存到公共网关了,那全世界的人就都能够通过公共网关流畅的运行了。