经过初步测试,通过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在文件开头找到
12这是通过在meta设置文件名之后在这个位置
在这里确定的文件url。
因为每个游戏的index都不一样,如果为每个游戏都上传一个html,我认为是很没有必要的,所以我决定把这个变成一个通用的模拟器页面,通过get传参的方式传入index。我js不太会,以下是网上找的获取get参数的方法,如果有更好的方法也可以更改:
12345function GetQueryString(name){ var reg=new RegExp("(^|&)"+name+"=([^&]*)(&|$)"); var r=window.location.search.substr(1).match(reg) ; if(r!=null)return unescape(r[2]);return null;}之后更改获取index的代码如下:
之后在进入模拟器页面时加上?index=onsyuri_index.json或者自己的json的url即可。
修改jsonsyuri.js文件主要是用来加载onsyuri.wasm的,而wasm没有任何依赖,可以直接上传ipfs,然后复制cid
之后打开js,这个生成的胶水代码完全没有格式化,直接用查找替换将onsyuri.wasm替换成上面的cid
这时候这个胶水文件就完成了,可以上传了
最终修改html胶水代码的url也是在meta里面设置的,修改为cid
1
这时候,html和js和wasm已经完全耦合在一起了,除了html,修改其中任何一个文件,都要按照上面的顺序修改并重新上传这3个文件,如果要修改,请确保自己神志清醒,知道自己在干什么。
游戏文件上传和生成索引建议拆包并开启懒加载,以获取最佳体验。不过应该是我多虑了,游戏资源拆包之后可能会生成上万个文件,大多是语音和序列帧动画等数量极多的文件,不知道ipfs能够索引的最大文件数量是多大,不过这么长的哈希,应该是不会冲突了吧即使我上传100G大合集应该也不会吧。
拆包需要自行编译nsadec或者用其他软件拆包,这里不多介绍。计算cid的方法,我也不太懂哈希,之前调库瞎搞搞了一晚上都没算出跟上传的一样的,所以不要管怎么计算cid了,从调库变成系统调用ipfs,如果是使用的ipfs desktop,在设置勾上“控制台”
修改onsyuri_index.py,注意,以下并非规范操作,且不知道会有什么其他影响,谨慎使用
1234567891011def make_filelist(inpath, urlbase): files = [] for _root, _dirs, _files in os.walk(inpath): for file in _files: path = os.path.join(_root, file) relpath = os.path.relpath(path, inpath).replace('\\', '/') #url = urlbase + relpath if urlbase!="" else "" url=os.popen(f"ipfs add -nq \’{path}\’").read()[:-1] if url=="": files.append({"path": relpath}) else :files.append({"path": relpath, "url": url}) return filespath的必须要用引号包围,有一些文件命名不规范,名字里面带有空格。
-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
那这个使用的链接应为
1http://127.0.0.1:8080/ipfs/QmX6UfTaWxiKfaPh9PQ59ExACboGr9TUvCs3pVtMcExsJj?index=Qmf9rq18AMbgsBiCwmrCNxxsnbsk3BLBwT47i3h1UfC6UR
效果如下:
用公共网关也可以但是卡得几乎不能玩
如果要分享给别人玩,目前没有什么好的方法,只能让对方也装上ipfs desktop,使用自己的节点来访问,国内节点之间连接的速度还是可以接受的。
如果将来使用这种方式的人多了,资源终于缓存到公共网关了,那全世界的人就都能够通过公共网关流畅的运行了。