虚拟文件系统 (vfs) 是 Ant 引擎的核心模块。在 wiki 上有介绍 ,blog 上也有总结。
最近在按前段时间拟定的思路重构编辑器。在这个过程中对 vfs 有了一些新想法。短期内不打算把工作重心放到重构 vfs 上面,先记录一下。
最早设计 vfs 的时候,是从网络文件系统的角度看待它的。我把它设想为一个类似 git 的组织方式,带版本控制的网络文件系统。所以,很多设计思路都是延续这个而来。但是,经过了这些年的数次重构,我对最初的思路产生了一些怀疑。
其中,最重要的一条:在游戏运行时,游戏程序看到的 vfs 是一个树结构的不变快照。这样,它像 git 一样,就可以用一个 Merkle tree 的 hash 值就可以代表这个快照,也可以方便的通过网络同步它。
为了实现编辑器,我们在这个设计上打了一些补丁,让编辑器可以在运行时动态的修改它。而我今天反思,“不变快照” 这一点是否是多余的?或者并不需要这个约束,也可以用简单的方案实现现在所有的功能。
经过一些思考后,我认为可以用这样一个新方案:
vfs 是一个在运行时可以动态增删的树结构,而这个树结构只存在于内存中,不需要持久化。一开始,vfs 只有一个空的根目录。
在运行时,需要不断的对 vfs 进行增改。把空的根目录扩展出更多的文件。我们可以设置一个路径 path 为一个特定的 hash 值。如果这个 path 中的任意一个子目录不存在,都应该被立刻创建出来。如果 path 对应的文件已经存在,则覆盖掉原有的值。即:vfs 是一颗树,每个叶节点都是一个 hash 值。
可以把 vfs 树中任意一个 hash 值绑定内容。这个内容可以是内存数据块,也可以是一个本地文件(加上时间戳)。hash 值是数据内容的 sha1 ,所以同一个 hash 值只可以(也只需要)绑定一次。
另有一个模块,可以递归计算本地文件目录:这包括所有文件及子目录的 hash 。生成一张表。如果程序在本地启动,不连接文件服务器,那么在启动时,计算本地目录的 hash ,用 3 中提到的 api 把相关 hash 全部绑定,再将 vfs 的根替换为计算好的 root hash 即可。
如果连接文件服务器,那么可以向文件服务器请求当前任意 path 的 hash ,以及任意 hash 对应的内容。并在本地 cache hash 的内容。这个环节和现在已有的实现完全相同。
遵循以上的方案,vfs 就不必遵循不变快照的假设。而是在运行时可以任意增删查改。和现有的方案相比:vfs 模块变成了管理一个纯内存数据结构,而不涉及网络同步,和外部数据如何存放于本地文件系统中无关。