-
-
Notifications
You must be signed in to change notification settings - Fork 565
excel
支持 bool,int,float,string,vector2,vector3,vector4 等等类型,它们的填写跟常规认知一致。
## | x1 | x3 | x4 | x5 | x6 | x7 | s1 | v2 | v3 | v4 |
---|---|---|---|---|---|---|---|---|---|---|
##type | bool | short | int | long | float | double | string | vector2 | vector3 | vector4 |
## | desc1 | id | desc4 | desc5 | desc6 | desc7 | desc1 | desc2 | desc3 | desc4 |
false | 10 | 100 | 1000 | 1.23 | 1.2345 | hello | 1,2 | 1,2,3 | 1,2,3,4 | |
true | 20 | 200 | 1000 | 1.23 | 1.2345 | world | 1,2 | 1,2,3 | 1,2,3,4 |
该类型数据包含两个字段, key和text, 其中 key 可以重复出现,但要求text完全相同,否则报错。这么设计是为了防止意外写重了key。注意:不允许key为空而text不为空
如果想填空的本地化字符串, key和text完全留空即可,工具会特殊对待,不会加入 key集合。
text的key和text字段都是string类型,因此在连续单元格或者sep产生的连续数据流模式中,同样要遵循用""来表达空白字符串的规则。
## | id | x&sep= |
---|---|---|
##type | int | text |
1 | /demo/key1#aaaa | |
2 | /demo/key2#bbbb | |
3 |
时间是常用的数据类型。Luban 特地提供了支持。
- 以纯字符串方式填写,填写格式为 以下 4 种。
- yyyy-mm-dd hh:mm:ss 如 1999-08-08 01:30:29
- yyyy-mm-dd hh:mm 如 2000-08-07 07:40
- yyyy-mm-dd hh 如 2001-09-05 07
- yyyy-mm-dd 如 2003-04-05
- 以 excel内置的时间格式填写
## | id | x |
---|---|---|
##type | int | datetime |
1 | 1999-09-09 01:02:03 | |
2 | 1999-09-09 01:02 | |
3 | 1999-09-09 01 | |
4 | 1999-09-09 |
有时候会有一种变量,我们希望它 功能生效时填一个有效值,功能不生效里,用一个值来表示。 例如 int 类型,常常拿 0 或者-1 作无效值常量。 但有时候,0 或-1 也是有效值时,这种做法就不生效了。或者说 项目组内 有时候拿 0,有时候拿-1 作无效值标记,很不统一。我们借鉴 sql 及 c#,引入 可空值概念,用 null 表达空值。
## | id | x | color |
---|---|---|---|
##type | int | int? | QualityColor? |
1 | 1 | A | |
2 | null | B | |
3 | 2 | null |
vector3 有三个字段 float x, float y, float z, 适合用于表示坐标之类的数据。
## | id | x2 | x3 | x4 |
---|---|---|---|---|
##type | int | vector2 | vector3 | vector4 |
1 | 1,2 | 11,22,33 | 12,33,44,55 | |
2 | 2,3 | 22,44,55 | 6.5,4.7,8.9 |
array与list类型都能表示列表,它们区别在于array生成的代码为数组,而list生成代码为列表。例如"array,int"生成的c#代码类型为 int[],而"list,int"生成的c#代码类型为 List<int>。
## | id | arr1 | arr2 | arr3&sep=| | arr4 | |||||
##type | int | array,int | list,int | list,string | list,string | |||||
## | id | desc1 | desc2 | desc3 | desc4 | |||||
1 | 1,2,3 | 1 | 2 | xx|yy | xxx | zzz | ||||
2 | 2;4 | 3 | 4 | 5 | aaaa|bbbb|cccc | aaa | bbb | ccc | ||
3 | 2|4|6 | 3 | 4 | 5 | 6 | aaaa|bbbb|cccc | aaa | bbb | ccc |
以枚举名或者别名或者值的方式填写枚举值。
在xml中定义
<enum name="ItemQuality">
<var name="WHITE" alias="白" value="0"/>
<var name="GREEN" alias="绿" value="1"/>
<var name="RED" alias="红" value="2"/>
</enum>
或者在 __enums__.xlsx 中 定义
## | full_name | flags | unique | comment | tags | *items | ||||
##+ | name | alias | value | comment | tags | |||||
ItemQuality | false | true | WHITE | 白 | 0 | |||||
GREEN | 绿 | 1 | ||||||||
RED | 红 | 2 |
数据表如下
## | id | quality | quality2 |
---|---|---|---|
##type | int | ItemQuality | ItemQuality |
1 | 白 | RED | |
2 | GREEN | 红 | |
3 | RED | WHITE | |
4 | 1 | 0 |
经常会碰到,某个字段是结构,尤其这个结构在很多配置里都会复用。
假设任务中包含一个 奖励信息 字段
在xml中定义
<bean name="Reward">
<var name="item_id" type="int"/>
<var name="count" type="int"/>
<var name="desc" type="string">
</bean>
或者在 __beans__.xlsx 里定义
## | full_name | sep | comment | fields | ||||
##+ | name | type | group | comment | tags | |||
Reward | item_id | int | 道具id | |||||
count | int | 个数 | ||||||
desc | string | 描述 |
数据表如下
## | id | reward | ||
##type | int | Reward | ||
## | id | 道具id | 个数 | 描述 |
1 | item1 | 1 | desc1 | |
2 | item2 | 100 | desc2 |
某个字段为结构列表的情形也很常见,比如说奖励信息列表包含多个奖励信息,每个奖励都有多个字段。
假设礼包中包含一个道具信息列表字段。支持3种填写模式,具体选择由策划灵活决定。
- 所有字段完全展开,每个单元格填一个元素。缺点是占用的列较多。如items1字段。
- 每个结构占据一个单元格,使用sep分割结构子字段。如items2字段。
- 整个列表占据一个单元格,使用sep分割列表及结构子字段。如items3字段。
xml中定义如下
<bean name="Reward">
<var name="item_id" type="int"/>
<var name="count" type="int"/>
<var name="desc" type="string">
</bean>
或者也可以在__beans__.xlsx中定义,此处不再赘述,==后面的涉及到结构定义的例子都只给xml的示例==。
数据表如下:
## | id | rewards1 | rewards2&sep=, | rewards3&sep=,| | |||||||
##type | int | list,Reward | list,Reward | list,Reward | |||||||
## | id | reward list desc1 | reward list desc2 | reward list desc3 | |||||||
1 | item1 | 1 | desc1 | item2 | 2 | desc2 | item1,1,desc1 | item2,2,desc2 | item3,3,desc3 | item1,1,desc1|item2,2,desc2 | |
2 | item1 | 1 | desc1 | item1,1,desc1 | item2,2,desc2 | item1,1,desc1|item2,2,desc2|item3,1,desc3 |
或者可以用多级标题头对每个元素单独限定
## | id | name | rewards | ||||||||
##type | int | string | list,Reward | ||||||||
##+ | 0 | 1 | 2 | ||||||||
##+ | item_id | num | desc | item_id | num | desc | item_id | num | desc | ||
1 | task1 | 1 | 10 | desc1 | 2 | 12 | desc2 | 3 | 13 | desc3 | |
2 | task1 | 3 | 30 | desc3 | 4 | 40 | desc4 | ||||
3 | task1 | 5 | 50 | desc5 |
有时候列表结构的每个结构字段较多,如果水平展开则占据太多列,不方便编辑,如果拆表,无论程序还是策划都不方便,此时可以使用多行模式。支持任意层次的多行结构列表(也即多行结构中的每个元素也可以是多行), name&multi_rows=1或者 *name 都可以表达一个多行解析的字段。
假设每个任务包含多个阶段,有一个阶段列表字段。
<bean name="Stage">
<var name="id" type="int"/>
<var name="name" type="string"/>
<var name="desc" type="string"/>
<var name="location" type="vector3"/>
<var name="reward_item_id" type="int"/>
<var name="reward_item_count" type="int"/>
</bean>
## | id | name | *stage2 | |||||
##type | int | string | list,Stage | |||||
## | id | desc | stage info | |||||
1 | task1 | 1 | stage1 | stage desc1 | 1,2,3 | 1001 | 1 | |
2 | stage2 | stage desc2 | 1,2,3 | 1001 | 1 | |||
3 | stage3 | stage desc3 | 1,2,3 | 1002 | 1 | |||
2 | task2 | 1 | stage1 | stage desc1 | 1,2,3 | 1001 | 1 | |
2 | stage2 | stage desc2 | 1,2,3 | 1002 | 1 |
有时候只想得到一个记录列表,无主键。mode="list"并且index为空,表示无主键表。
定义表
<table name="TbNotKeyList" value="NotKeyList" mode="list" input="not_key_list.xlsx"/>
示例数据表
## | x | y | z | num |
---|---|---|---|---|
##type | int | long | string | int |
1 | 1 | aaa | 123 | |
1 | 1 | bbb | 124 | |
1 | 2 | aaa | 134 | |
2 | 1 | aaa | 124 | |
5 | 6 | xxx | 898 |
多个key构成联合唯一主键。使用"+"分割key,表示联合关系。
定义表
<table name="TbUnionMultiKey" value="UnionMultiKey" index="key1+key2+key3" input="union_multi_key.xlsx"/>
示例数据表
## | key1 | key2 | key3 | num |
---|---|---|---|---|
##type | int | long | string | int |
1 | 1 | aaa | 123 | |
1 | 1 | bbb | 124 | |
1 | 2 | aaa | 134 | |
2 | 1 | aaa | 124 | |
5 | 6 | xxx | 898 |
多个key,各自独立唯一索引。与联合索引写法区别在于使用 ","来划分key,表示独立关系。
定义表
<table name="TbMultiKey" value="MultiKey" index="key1,key2,key3" input="multi_key.xlsx"/>
示例数据表
## | key1 | key2 | key3 | num |
---|---|---|---|---|
##type | int | long | string | int |
1 | 2 | aaa | 123 | |
2 | 4 | bbb | 124 | |
3 | 6 | ccc | 134 | |
4 | 8 | ddd | 124 | |
5 | 1 | eee | 898 |
有一些配置全局只有一份,比如 公会模块的开启等级,背包初始大小,背包上限。此时使用单例表来配置这些数据比较合适。
## | guld_open_level | bag_init_capacity | bag_max_capacity | newbie_tasks |
---|---|---|---|---|
##type | int | int | int | list,int |
## | desc1 | desc 2 | desc 3 | desc 4 |
10 | 100 | 500 | 10001,10002 |
大多数表都是横表,即一行一个记录。有些表,比如单例表,如果纵着填,一行一个字段,会比较舒服。A1为##column表示使用纵表模式。 上面的单例表,以纵表模式填如下。
##column | ##type | ## | |
guild_open_level | int | desc1 | 10 |
bag_init_capacity | int | desc2 | 100 |
bag_max_capacity | int | desc3 | 500 |
newbie_tasks | list,int | desc4 | 10001,10002 |
游戏配置中经常要填写诸如道具id之类的外键数据,这些数据必须是合法的id值,luban支持生成时检查id的合法性,如果有误,则打出警告。不只是表顶层字段,列表及嵌套结构的子字段也支持完整的引用检查。
<bean name="Reward">
<var name="item_id" type="int" ref="item.TbItem"/>
<var name="count" type="int"/>
<var name="desc" type="string">
</bean>
## | id | item_id | items | reward | rewards&sep=, | ||||
##type | int | int | int&ref=item.TbItem | list,int&ref=item.TbItem | reward | ||||
## | id | desc1 | desc2 | desc3 | desc4 | ||||
1 | 1001 | 1001,1002 | 1001 | 10 | item1 | 1001,10,item1 | 1002,2,item2 | ||
2 | 1002 | 1003,1004,1005 | 1002 | 10 | item2 | 1004,10,item4 | 1005,2,item5 | 1010,1,item10 |
配置中经常要填写资源路径,比如道具icon的资源,这些数据都是string类型,非常容易填写出错,导致运行时无法正常显示。luban支持unity与ue4资源的合法性检查以及通用型文件路径检查。不只是表顶层字段,列表及嵌套结构的子字段也支持完整的引用检查。
对于这些字段添加属性 path=unity或者path=ue或path=normal;xxxx。
## | id | icon |
---|---|---|
##type | int | string&path=unity |
## | id | icon desc |
1 | Assets/UI/item1.jpg | |
2 | Assets/UI/item2.jpg |
灵活的分组定义,不仅仅是client和server分组。支持以下分组粒度:
- 表级别分组
- 字段级别分组(任意bean字段粒度,而不仅限于顶层字段)
开发期经常会制作一些仅供开发使用的配置,比如测试道具,比如自动化测试使用的配置,希望在正式发布时不导出这些数据。
## | id | name | |
---|---|---|---|
##type | int | string | |
## | id | desc1 | 注释 |
1 | item1 | 永远导出 | |
## | 2 | item2 | 永远不导出 |
test | 4 | item4 | --export_exclude_tags test 时不导出 |
TEST | 5 | item5 | --export_exclude_tags test 时不导出 |
dev | 6 | item6 | --export_exclude_tags dev 时不导出 |
7 | item7 | 永远导出 |
目前只对容器类型字段支持多行。字段名前加*,如 *stages,或者添加multi_rows=1参数也行,如stages#multi_rows=1。 一旦标记字段为多行,每行会作为字段的一个元素读入,例如 list,bean类型,则每行读入一个bean结构。
多行可以嵌套,即多行字段中,某个字段本身也可以是多行记录。 示例可参见multi_rows_record
<bean name="Stage">
<var name="id" type="int"/>
<var name="name" type="string"/>
<var name="desc" type="string"/>
<var name="location" type="vector3"/>
<var name="reward_item_id" type="int"/>
<var name="reward_item_count" type="int"/>
</bean>
## | id | name | *stages | |||||
##type | int | string | list,Stage | |||||
## | id | desc | stage info | |||||
1 | task1 | 1 | stage1 | stage desc1 | 1,2,3 | 1001 | 1 | |
2 | stage2 | stage desc2 | 1,2,3 | 1001 | 1 | |||
3 | stage3 | stage desc3 | 1,2,3 | 1002 | 1 | |||
2 | task2 | 1 | stage1 | stage desc1 | 1,2,3 | 1001 | 1 | |
2 | stage2 | stage desc2 | 1,2,3 | 1002 | 1 |
在多行数据或者深层次嵌套的数据中,如果数据字段较多,填写时不易区分子元素。luban提供层级标题实现深层次的子字段对应。以上面的多行数据列表为例,第一列为##+表示这是个子字段行。
- 普通bean结构的子标题
## | id | name | stage | ||||
##type | int | string | Stage | ||||
##+ | name | desc | location | item_id | num | ||
## | id | name | desc2 | desc3 | desc4 | desc5 | desc6 |
1 | task1 | stage1 | stage desc1 | 1,2,3 | 1001 | 1 | |
2 | task2 | stage2 | stage desc2 | 3,4,5 | 2001 | 3 |
- list,bean 的多行展开多级子标题
## | id | name | stages | |||||
##+ | id | name | desc | location | item_id | num | ||
##type | int | string | list,Stage | |||||
## | id | desc1 | desc1 | desc2 | desc3 | desc4 | desc5 | desc6 |
1 | task1 | 1 | stage1 | stage desc1 | 1,2,3 | 1001 | 1 | |
2 | stage2 | stage desc2 | 1,2,3 | 1001 | 1 | |||
3 | stage3 | stage desc3 | 1,2,3 | 1002 | 1 | |||
2 | task2 | 1 | stage1 | stage desc1 | 1,2,3 | 1001 | 1 | |
2 | stage2 | stage desc2 | 1,2,3 | 1002 | 1 |
- list,bean 的水平展开多级子标题
## | id | name | items | ||||||||
##type | int | string | list,Item | ||||||||
##+ | 0 | 1 | 2 | ||||||||
##+ | item_id | num | desc | item_id | num | desc | item_id | num | desc | ||
1 | task1 | 1 | 10 | desc1 | 2 | 12 | desc2 | 3 | 13 | desc3 | |
2 | task1 | 3 | 30 | desc3 | 4 | 40 | desc4 | ||||
3 | task1 | 5 | 50 | desc5 |
- map 类型的多级子标题
## | id | lans | |||
##type | int | map,string,string | |||
##+ | ch-zn | en | jp | fr | |
1 | 苹果 | apple | aaa | aaa | |
2 | 香蕉 | banana | bbb | bbb |
支持OOP的类型继承体系,方便表达多类型的数据,常用于技能、AI等模块。类型继承是luban类型系统的灵魂,如果没有类型继承,不可能简洁地表达任意复杂数据结构,因而也不可能定义并且从配置中读取复杂的配置数据。
实践中像技能和AI之类的数据,一般用编辑器制作,使用json之类的格式保存,而不是在excel中编辑。
<bean name="Shape">
<bean name="Circle">
<var name="radius" type="float"/>
</bean>
<bean name="Rectangle" alias="长方形">
<var name="width" type="float"/>
<var name="height" type="float"/>
</bean>
<bean name="Curve">
<bean name="Line" alias="直线">
<var name="param_a" type="float"/>
<var name="param_b" type="float"/>
</bean>
<bean name="Parabola" alias="抛物线">
<var name="param_a" type="float"/>
<var name="param_b" type="float"/>
</bean>
</bean>
</bean>
## | id | shapes&sep=, | |||
##type | int | list,Shape | |||
## | id | shape desc | |||
1 | Circle,10 | Rectangle,100,200 | |||
2 | Circle,20 | Rectangle,100,200 | Line,5,8 | Parabola,15,30 |
我们希望excel中单元格留空时,该字段取指定值,而不是默认的false,0之类。通过定义字段的default=xxx属性来指定默认值。
如示例,id=2的记录,x1与x2皆为空,x1=0,x2=-1。
## | id | x1 | x2&default=-1 |
---|---|---|---|
##type | int | int | int |
## | id | desc1 | desc2 |
1 | 10 | 20 | |
2 | |||
3 | 30 |
游戏里经常会出现一些常用的类似枚举的值,比如说 升级丹的 id,在很多地方都要填,如果直接它的道具 id,既不直观,也容易出错。 Luban 支持常量替换。如示例,导出时SHENG_JI_DAN会被替换为11220304。
<enum name="EFunctionItemId">
<var name="SHENG_JI_DAN" alias="升级丹" value="11220304"/>
<var name="JIN_JIE_DAN" alias="进阶丹" value="11220506"/>
</enum>
## | id | item_id |
---|---|---|
##type | int | int&convert=EFunctionItemId |
## | id | desc |
1 | SHENG_JI_DAN | |
2 | 进阶丹 | |
3 | 1001 |
- 可以几个表都放到一个xlsx中,每个表占一个sheet。 input="[email protected]"
- 可以一个表拆分为几个xlsx。 input="a.xlsx,b.xlsx"
- 假设你要创建的配置为装备表.
- 在MyConfigs/Datas 目录下创建 equip.xlsx(实践中推荐按模块创建子目录,在模块目录创建配置,便于维护管理), 其内容如下
## | id | name | attr |
---|---|---|---|
##type | int | string | int |
1 | equip1 | 10 | |
2 | equip2 | 15 |
- 在 MyConfigs/Datas/tables.xlsx 里新增一行。 有些不相关列被忽略了
## | full_name | value_type | define_from_excel | input | ... |
---|---|---|---|---|---|
demo.TbItem | Item | true | 物品表.xlsx |
- 至此,完成添加新表工具。 运行 check.bat 检查是否成功生成!
- A1 单元格必须是 ## 或者 ##column(表示纵表)。
- 第1列单元格为 ##type 表示这行是 类型定义行
- 第1列单元格以##开头 表示这是注释行,如果有多个##行,默认以第一个行作为代码中字段的注释,你可以通过##comment 显式指定某行为代码注释行。
- 填写多级字段名行时,以##+或##var或##field 表示这是次级字段行
## | id | name | stages | |||||
##+ | id | name | desc | location | item_id | num | ||
##type | int | string | list,Stage | |||||
## | id | desc1 | desc1 | desc2 | desc3 | desc4 | desc5 | desc6 |
##comment | id | 名字 | 注释1 | desc2 | desc3 | desc4 | desc5 | desc6 |
1 | task1 | 1 | stage1 | stage desc1 | 1,2,3 | 1001 | 1 | |
2 | stage2 | stage desc2 | 1,2,3 | 1001 | 1 | |||
3 | stage3 | stage desc3 | 1,2,3 | 1002 | 1 | |||
2 | task2 | 1 | stage1 | stage desc1 | 1,2,3 | 1001 | 1 | |
2 | stage2 | stage desc2 | 1,2,3 | 1002 | 1 |
- 如果未指定sheet,则默认会读取所有sheet
- 可以用 [email protected] 指定只读入这个sheet数据
- 如果A1单元格数据不以##开头,则会被当作非数据sheet,被忽略
luban会智能猜测出它的编码,正确处理。
除了枚举、bean以外的数据,都可以留空。自动取默认值。注意非空字段的默认值是初始值,可空变量的默认值为null。例如int默认值是0,但int?的默认值是null。
只对excel格式有效。在字段名上加上 xxx&default=value,则所有留空的单元格都会自动取value。如下图,id=2的记录,count=10,desc=haha。
## | id | count&default=10 | desc&default=haha |
---|---|---|---|
##type | int | int | string |
1 | 1 | abc | |
2 |