游戏公司很多都会把Excel作为游戏数据的配置工具,已经很少有公司会针对性的开发一款地图编辑器。这么做的优点也很明显:
- 技能互通,不需要新的学习过程。
- excel的功能已经足够强大,便捷程度往往高于一款粗糙的编辑器。
先来说说xlsx文件格式
xlsx文件实际上是一种压缩文件,在重命名成zip后就可以通过压缩软件打开。有点类似于一个VFS,其中的文本信息,图片都按照一定的目录结构存放。而其中表格的信息被以xml的格式存放在worksheets文件夹下,而我们最为关心得每个格子里的文本信息则被存在shareStrings.xml中。
这样一来,我们很快就可以理解为什么通过一些库读取或写入excel文件是多么痛苦的一件事了。1.解压,2.需要访问xml文件,3.数据还需要几个文件的联动访问(有点类似ER数据库)。特别是作为一个高效的服务端的开发人员,这种低效的加载过程是不能接受的(当然可以通过prefetch,cache等方法来改善这个效果问题)。
这还没完,直接读取excel还有其他问题存在
- 游戏中的配置数据一般是有类型的,比如int,string。如果一个配置数据是int的,策划写成了"abc",那我们高贵的服务器读取了,会发生什么?它需要忙着去验证配置表的合法性,这就蛋疼了。
- 有时候想引入一些高级的纠错功能。比如drop表控制着游戏中的掉落,而掉落数据需要引用到item表的id。那么drop表如果掉出一些不存在的item会怎么样。这个坑看来又是需要服务端去填了。
- 如果多个进程同时访问excel文件,可能会出现句柄被占用的情况,造成文件打开失败。
一个trivial的想法
于是很容易想到,我们可以通过一个工具把excel转化为服务端语言(lua,C++,C#等)的所使用的代码。然后,把这段代码内嵌到服务器中,服务器就可以安心地访问了。
方案的优点:
- 数据加载的过程对比与excel加载更加高效快速。并且分离了服务端和xlsx的关系(有时候或有的语言找一个excel库其实并不容易)。
- 可以支持数据表的检查,纠错等功能。
- 分离了数据检查的逻辑到一个工具中实现,解放了服务器开发的码农们。
可以先看一下最终的自动转化后的代码(C#,EPPlus.dll)
转化程序的工作流程
DataLoad
把excel数据加载到转换程序内存中。过程中,需要用到excel文件类库的api来读取xlsx文件的内容。最终每一格的数据都会被存到内存中(类似一个二维的string数组)。
DataCheck
检查下字段类型是不是自己希望的(比如int的格子不能存"abc")。此外,跨表的外键查询的情况也可以再这一步的完成。如果出现错误,可以写log文件等方式进行反馈,让策划重新去改表吧。
我们可以按照需求实现各种想要去做的检查规则。比如,我们希望道具掉落的概率只能是0-1之间。比如,我们希望道具的id应该是八位数字并且以53开头。比如,我们希望某一个数组的成员数量不能大于10。
这些规则都可以在这一步予以支持。
Export
这一步可以实现为多态。
public interface IExporter
{
void Prework();
void ExportRecord();
}
然后,我们就可以按我们的需求,实现CsharpExporter,JsonExporter了。
这一步的工作主要是把内存里的数据以codegen的方式写到方便服务器读取的文件中。可以是代码的方式,也可以是数据文件的方式(比如转为CSV)。