diff --git a/README.md b/README.md index f6c9b90..107bff6 100644 --- a/README.md +++ b/README.md @@ -9,18 +9,21 @@ ![icon](docs/images/icon.png) ----- + ## links + - [README - English](./README.en-us.md) - [github link](https://github.com/focus-creative-games/luban) - [gitee link](https://gitee.com/focus-creative-games/luban) ----- + +----- ## 介绍 - 在中大型游戏项目中,excel配置表时常出现较复杂的数据结构,常规的导表工具面对此类需求要么无法支持,要么就强迫策划和程序使用拆表等奇技淫巧,严重影响设计和开发效率。另外具有复杂GamePlay的游戏中,技能、行为树、关卡之类的功能也有非常复杂的数据结构,它们往往使用自定义编辑器制作,并以json、xml等文件格式保存,以excel为中心的导表工具无法处理这些数据,给策划和程序的工作流带来麻烦。 luban相较于常规的excel导表工具有以下核心优势: + - 增强了excel格式。可以比较简洁地excel配置**任意复杂**的数据,像子结构、结构列表,以及更复杂的深层次的嵌套结构都能直接解析处理。 - 完备的类型系统和多原始数据支持(excel、xml、json、lua、yaml),可以轻松表达和解析**任意复杂**的数据。意味着传统excel导表工具无法处理的技能、行为树、副本等等复杂配置,luban也能够统一处理了,彻底将程序从复杂的配置解析中解放出来。 - 支持binary、**protobuf**(同时可以生成相应的pb定义)、**msgpack**、**flatbuffers**、json、lua等多种导出数据格式。 @@ -30,6 +33,7 @@ luban相较于常规的excel导表工具有以下核心优势: - 通用型生成工具。也可以用于生成协议、数据库之类的代码,甚至可以用作对象缓存服务。 ## 文档 + - [快速上手](https://github.com/focus-creative-games/luban/wiki/start_up) - [**wiki**](https://github.com/focus-creative-games/luban/wiki) ,比较完善,有使用疑问,请先查看此wiki。 - **示例项目** ([github](https://github.com/focus-creative-games/luban_examples)) ([gitee](https://gitee.com/focus-creative-games/luban_examples)) @@ -40,6 +44,7 @@ luban相较于常规的excel导表工具有以下核心优势: - 邮箱: taojingjian#gmail.com ## 特性 + - 支持excel族、json、xml、lua、yaml 多种数据格式,基本统一了游戏常见的配置数据 - **强大完备的类型系统**。**可以优雅表达任意复杂的数据结构**。支持所有常见原生类型、text本地化类型、datetime类型、vector{2,3,4}、容器类型list,set,map、枚举和结构、**多态结构**以及**可空类型**。 - 支持增强的excel格式。可以在excel里比较简洁填写出任意复杂的嵌套数据。 @@ -50,8 +55,8 @@ luban相较于常规的excel导表工具有以下核心优势: - 多种导出数据格式支持。支持binary、json、**protobuf**、**msgpack**、**flatbuffers**、lua、xml、erlang、**xlsx** 及自定义的导出数据格式 - 支持xlsx与json、lua、xml、yaml等格式之间互转 - 强大灵活的定制能力 - - 支持代码模板,可以用自定义模板定制生成的代码格式 - - **支持数据模板**,可以用模板文件定制导出格式。意味着可以在不改动现有程序代码的情况下,把luban当作**配置处理前端**,生成自定义格式的数据与自己项目的配置加载代码配合工作。开发已久的项目或者已经上线的老项目,也能从luban强大的数据处理工作流中获益 + - 支持代码模板,可以用自定义模板定制生成的代码格式 + - **支持数据模板**,可以用模板文件定制导出格式。意味着可以在不改动现有程序代码的情况下,把luban当作**配置处理前端**,生成自定义格式的数据与自己项目的配置加载代码配合工作。开发已久的项目或者已经上线的老项目,也能从luban强大的数据处理工作流中获益 - 支持数据标签。 可以选择导出符合要求的数据,发布正式数据时策划不必手动注释掉那些测试数据了 - 强大的数据校验能力。支持内建数据格式检查;支持ref表引用检查(策划不用担心填错id);支持path资源检查(策划不用担心填错资源路径);支持range检查 - 支持常量别名。策划不必再为诸如 升级丹 这样的道具手写具体道具id了 @@ -61,53 +66,52 @@ luban相较于常规的excel导表工具有以下核心优势: - 统一了自定义编辑器的配置数据。与Unity和UE4的自定义编辑器良好配合,为编辑器生成合适的加载与保存json配置的的c#(Unity)或c++(UE4)代码。保存的json配置能够被luban识别和处理。 - 支持emmylua anntations。生成的lua包含符合emmylua 格式anntations信息。配合emmylua有良好的配置代码提示能力 - **本地化支持** - - 支持时间本地化。datetime类型数据会根据指定的timezone,转换为目标地区该时刻的UTC时间,方便程序使用。 - - 支持文本静态本地化。导出时所有text类型数据正确替换为最终的本地化字符串。绝大多数的业务功能不再需要运行根据本地化id去查找文本的内容,简化程序员的工作。 - - 支持文本动态本地化。运行时动态切换所有text类型数据为目标本地化字符串。 - - 支持 main + patches 数据合并。在基础数据上,施加差分数据,生成最终完整数据,适用于制作有细微不同的多地区的配置数据。 - - [TODO] 【独创】 支持任意粒度和任意类型数据(如int,bean,list,map)的本地化。 -- 生成极快。支持常规的本地缓存增量生成模式,也支持云生成模式。MMORPG这样大型项目也能秒内生成。日常增量生成基本在300ms以内,项目后期极大节省了迭代时间。另外支持**watch监测模式**,数据目录变化立即重新生成。 + - 支持时间本地化。datetime类型数据会根据指定的timezone,转换为目标地区该时刻的UTC时间,方便程序使用。 + - 支持文本静态本地化。导出时所有text类型数据正确替换为最终的本地化字符串。绝大多数的业务功能不再需要运行根据本地化id去查找文本的内容,简化程序员的工作。 + - 支持文本动态本地化。运行时动态切换所有text类型数据为目标本地化字符串。 + - 支持 main + patches 数据合并。在基础数据上,施加差分数据,生成最终完整数据,适用于制作有细微不同的多地区的配置数据。 + - [TODO] 【独创】 支持任意粒度和任意类型数据(如int,bean,list,map)的本地化。 +- 生成极快。支持常规的本地缓存增量生成模式,也支持云生成模式。MMORPG这样大型项目也能秒内生成。日常增量生成基本在300ms以内,项目后期极大节省了迭代时间。另外支持**watch监测模式**,数据目录变化立即重新生成。 - **LubanAssistant**,Luban的Excel插件。支持把json、lua、xml等文本格式的配置数据加载到excel中,批量编辑处理,最后再保存回原文件,较好地解决大型项目中多人合作数据编辑冲突合并的问题,较好解决在编辑器中制作的配置难以在excel中批量修改的问题。 - Excel2TextDiff。将excel转成文本后再diff,清晰对比excel版本之间内容变化。 - 支持主流的游戏开发语言 - - c++ (11+) - - c# (.net framework 4+. dotnet core 3+) - - java (1.6+) - - go (1.10+) - - lua (5.1+) - - js 和 typescript (3.0+) - - python (3.0+) - - erlang (18+) - - rust (1.5+) - - 其他protobuf、msgpack、flatbuffers支持的语言 + - c++ (11+) + - c# (.net framework 4+. dotnet core 3+) + - java (1.6+) + - go (1.10+) + - lua (5.1+) + - js 和 typescript (3.0+) + - python (3.0+) + - erlang (18+) + - rust (1.5+) + - 其他protobuf、msgpack、flatbuffers支持的语言 - 支持主流引擎和平台 - - unity + c# - - unity + [tolua](https://github.com/topameng/tolua)、[xlua](https://github.com/Tencent/xLua) - - unity + [ILRuntime](https://github.com/Ourpalm/ILRuntime) - - unity + [puerts](https://github.com/Tencent/puerts) - - unity + [GameFramework](https://github.com/EllanJiang/GameFramework) - - unity + [ET游戏框架](https://github.com/egametang/ET) - - unreal + c++ - - unreal + [unlua](https://github.com/Tencent/UnLua) - - unreal + [sluaunreal](https://github.com/Tencent/sluaunreal) - - unreal + [puerts](https://github.com/Tencent/puerts) - - cocos2d-x + lua - - cocos2d-x + js - - [skynet](https://github.com/cloudwu/skynet) - - 微信小程序平台 - - 其他家基于js的小程序平台 - - 其他所有支持lua的引擎和平台 - - 其他所有支持js的引擎和平台 + - unity + c# + - unity + [tolua](https://github.com/topameng/tolua)、[xlua](https://github.com/Tencent/xLua) + - unity + [ILRuntime](https://github.com/Ourpalm/ILRuntime) + - unity + [puerts](https://github.com/Tencent/puerts) + - unity + [GameFramework](https://github.com/EllanJiang/GameFramework) + - unity + [ET游戏框架](https://github.com/egametang/ET) + - unreal + c++ + - unreal + [unlua](https://github.com/Tencent/UnLua) + - unreal + [sluaunreal](https://github.com/Tencent/sluaunreal) + - unreal + [puerts](https://github.com/Tencent/puerts) + - cocos2d-x + lua + - cocos2d-x + js + - [skynet](https://github.com/cloudwu/skynet) + - 微信小程序平台 + - 其他家基于js的小程序平台 + - 其他所有支持lua的引擎和平台 + - 其他所有支持js的引擎和平台 ## 增强的excel格式 -luban支持在excel中解析任意复杂的数据结构,哪怕复杂如技能、行为树(但在实践中一般使用编辑器制作这些数据,以json格式保存,而不会在excel里填写)。下面从简单到复杂展示在luban中配置这些数据的方式。 +luban支持在excel中解析任意复杂的数据结构,哪怕复杂如技能、行为树(但在实践中一般使用编辑器制作这些数据,以json格式保存,而不会在excel里填写)。下面从简单到复杂展示在luban中配置这些数据的方式。 ### 原生数据类型 支持 bool,int,float,string,text,datetime,vector2,vector3,vector4 等等类型,它们的填写跟常规认知一致。 - |##| x1 | x3 | x4 | x5 | x6 | x7 | s1 | s2&sep=# | v2 | v3 | v4 | t1 | | -| - | - | - | - | - | - | - | - | - | - | - | - | |##type|bool|short|int|long|float|double|string|text |vector2|vector3|vector4|datetime| @@ -115,11 +119,11 @@ luban支持在excel中解析任意复杂的数据结构,哪怕复杂如技能 || false| 10| 100| 1000| 1.23| 1.2345|hello |key1#world1|1,2|1,2,3|1,2,3,4|1999-10-10 11:12:13| || true | 20| 200| 1000| 1.23| 1.2345|world |key2#world2|1,2|1,2,3|1,2,3,4|1999-10-12 11:12:13| - ### 原生数据列表 array与list类型都能表示列表,它们区别在于array生成的代码为数组,而list生成代码为列表。例如"array,int"生成的c#代码类型为 int[],而"list,int"生成的c#代码类型为 List<int>。 + @@ -175,19 +179,20 @@ array与list类型都能表示列表,它们区别在于array生成的代码为
##
- - ### 枚举 + 以枚举名或者别名或者值的方式填写枚举值。 在xml中定义 + ```xml - - - + + + ``` + 或者在 \_\_enums\_\_.xlsx 中 定义 @@ -199,7 +204,6 @@ array与list类型都能表示列表,它们区别在于array生成的代码为
- 数据表如下 | ##|id| quality| quality2 | @@ -210,23 +214,23 @@ array与list类型都能表示列表,它们区别在于array生成的代码为 | | 3| RED | WHITE | | | 4| 1 | 0 | - - ### 嵌套子结构 + 经常会碰到,某个字段是结构,尤其这个结构在很多配置里都会复用。 假设任务中包含一个 奖励信息 字段 在xml中定义 + ```xml - - - + + + ``` -或者在 \_\_beans__.xlsx 里定义 +或者在 \_\_beans__.xlsx 里定义 @@ -236,7 +240,6 @@ array与list类型都能表示列表,它们区别在于array生成的代码为
##full_namesepcommentfields
descstring描述
- 数据表如下 @@ -258,20 +261,21 @@ array与list类型都能表示列表,它们区别在于array生成的代码为 - + - +
1item11desc110011desc1
2item2100desc21002100desc2
- ### 简单结构列表 + 某个字段为结构列表的情形也很常见,比如说奖励信息列表包含多个奖励信息,每个奖励都有多个字段。 假设礼包中包含一个道具信息列表字段。支持3种填写模式,具体选择由策划灵活决定。 + - 所有字段完全展开,每个单元格填一个元素。缺点是占用的列较多。如items1字段。 - 每个结构占据一个单元格,使用sep分割结构子字段。如items2字段。 - 整个列表占据一个单元格,使用sep分割列表及结构子字段。如items3字段。 @@ -280,9 +284,9 @@ xml中定义如下 ```xml - - - + + + ``` @@ -315,17 +319,17 @@ xml中定义如下 1 -item11desc1item22desc2 -item1,1,desc1item2,2,desc2item3,3,desc3 -item1,1,desc1|item2,2,desc2 +10011desc110022desc2 +1001,1,desc11002,2,desc21003,3,desc3 +1001,1,desc1|1002,2,desc2 2 -item11desc1 -item1,1,desc1item2,2,desc2 -item1,1,desc1|item2,2,desc2|item3,1,desc3 +10011desc1 +1001,1,desc11002,2,desc2 +1001,1,desc1|1002,2,desc2|1003,1,desc3 @@ -364,24 +368,25 @@ xml中定义如下 item_idnumdesc -1task1110desc1212desc2313desc3 -2task1330desc3440desc4 -3task1550desc5 +1task1100110desc1100212desc2100313desc3 +2task1100330desc3100440desc4 +3task1100550desc5 ### 多行结构列表 + 有时候列表结构的每个结构字段较多,如果水平展开则占据太多列,不方便编辑,如果拆表,无论程序还是策划都不方便,此时可以使用多行模式。支持任意层次的多行结构列表(也即多行结构中的每个元素也可以是多行), name&multi_rows=1或者 *name 都可以表达一个多行解析的字段。 假设每个任务包含多个阶段,有一个阶段列表字段。 ```xml - - - - - - + + + + + + ``` @@ -433,6 +438,7 @@ xml中定义如下 有时候只想得到一个记录列表,无主键。mode="list"并且index为空,表示无主键表。 定义表 + ```xml ``` @@ -448,12 +454,12 @@ xml中定义如下 ||2|1|aaa|124| ||5|6|xxx|898| - ### 多主键表(联合索引) 多个key构成联合唯一主键。使用"+"分割key,表示联合关系。 定义表 + ```xml
``` @@ -474,12 +480,13 @@ xml中定义如下 多个key,各自独立唯一索引。与联合索引写法区别在于使用 ","来划分key,表示独立关系。 定义表 + ```xml
``` 示例数据表 - + |##|key1|key2|key3| num| |-|-|-|-|-| |##type|int|long|string|int| @@ -490,6 +497,7 @@ xml中定义如下 ||5|1|eee|898| ### 单例表 + 有一些配置全局只有一份,比如 公会模块的开启等级,背包初始大小,背包上限。此时使用单例表来配置这些数据比较合适。 | ##| guld_open_level | bag_init_capacity | bag_max_capacity | newbie_tasks | @@ -498,13 +506,10 @@ xml中定义如下 | ## |desc1 | desc 2 | desc 3 | desc 4 | | | 10 | 100| 500| 10001,10002 | - - ### 纵表 大多数表都是横表,即一行一个记录。有些表,比如单例表,如果纵着填,一行一个字段,会比较舒服。A1为##column表示使用纵表模式。 上面的单例表,以纵表模式填如下。 -
@@ -527,13 +532,14 @@ xml中定义如下
##column
### 引用检查 + 游戏配置中经常要填写诸如道具id之类的外键数据,这些数据必须是合法的id值,luban支持生成时检查id的合法性,如果有误,则打出警告。不只是表顶层字段,列表及嵌套结构的子字段也支持完整的引用检查。 ```xml - - - + + + ``` @@ -567,22 +573,21 @@ xml中定义如下 1 1001 1001,1002 - 100110item1 - 1001,10,item11002,2,item2 + 1001101001 + 1001,10,10011002,2,1002 2 1002 1003,1004,1005 - 100210item2 - 1004,10,item41005,2,item51010,1,item10 + 1002101002 + 1004,10,item41005,2,item51010,1,10010 - - ### 资源检查 + 配置中经常要填写资源路径,比如道具icon的资源,这些数据都是string类型,非常容易填写出错,导致运行时无法正常显示。luban支持unity与ue4资源的合法性检查以及通用型文件路径检查。不只是表顶层字段,列表及嵌套结构的子字段也支持完整的引用检查。 对于这些字段添加属性 path=unity或者path=ue或path=normal;xxxx。 @@ -591,11 +596,11 @@ xml中定义如下 | - | - | - | | ##type| int | string&path=unity| | ##|id | icon desc | -| | 1| Assets/UI/item1.jpg| -| | 2| Assets/UI/item2.jpg| - +| | 1| Assets/UI/1001.jpg| +| | 2| Assets/UI/1002.jpg| ### 分组导出 + 灵活的分组定义,不仅仅是client和server分组。支持以下分组粒度: - 表级别分组 @@ -603,22 +608,23 @@ xml中定义如下 ### 数据标签过滤 -开发期经常会制作一些仅供开发使用的配置,比如测试道具,比如自动化测试使用的配置,希望在正式发布时不导出这些数据。 +开发期经常会制作一些仅供开发使用的配置,比如测试道具,比如自动化测试使用的配置,希望在正式发布时不导出这些数据。 | ## | id | name | | | - | - | - | - | | ##type | int | string | | | ## | id | desc1| 注释 | -| | 1 | item1 | 永远导出 | -|##| 2 | item2 | 永远不导出 | +| | 1 | 1001 | 永远导出 | +|##| 2 | 1002 | 永远不导出 | |test| 4 | item4 | --export_exclude_tags test 时不导出 | |TEST| 5 | item5 | --export_exclude_tags test 时不导出 | |dev |6 | item6 | --export_exclude_tags dev 时不导出 | | | 7|item7| 永远导出 | - ## 高级特性 + ### 层级标题头 (hierarchy title) + 在多行数据或者深层次嵌套的数据中,如果数据字段较多,填写时不易区分子元素。luban提供层级标题实现深层次的子字段对应。以上面的多行数据列表为例,第一列为##+表示这是个子字段行。 - 普通bean结构的子标题 @@ -773,6 +779,7 @@ xml中定义如下 ### 可空数据类型 + 配置数据中经常有空值的语义需求,实际项目中往往混杂地使用0或-1表达空值,既不自然清晰也不统一。luban借鉴了c#中的可空变量的概念,特地提供可空数据支持。所有原生数据类型,以及enum、bean、和多态bean类型都有相应的可空数据类型。定义方式为 <类型名>?,与c#里的Nullable类型定义方式相同。例如 bool?,int?,long?,double?, EColor?, DemoType? |##|id|x1|x2|x3|x4|x5| @@ -783,34 +790,35 @@ xml中定义如下 ||2|null|null|null|null|null| ||3| ||||| - ### 类型继承(inheritance) + 支持OOP的类型继承体系,方便表达多类型的数据,常用于技能、AI等模块。类型继承是luban类型系统的灵魂,如果没有类型继承,不可能简洁地表达任意复杂数据结构,因而也不可能定义并且从配置中读取复杂的配置数据。 实践中像技能和AI之类的数据,一般用编辑器制作,使用json之类的格式保存,而不是在excel中编辑。 ```xml - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + ``` + @@ -845,8 +853,8 @@ xml中定义如下
##
- ### 字段默认值 + 我们希望excel中单元格留空时,该字段取指定值,而不是默认的false,0之类。通过定义字段的default=xxx属性来指定默认值。 如示例,id=2的记录,x1与x2皆为空,x1=0,x2=-1。 @@ -859,15 +867,14 @@ xml中定义如下 ||2| | | ||3| | 30| - ### 常量别名 游戏里经常会出现一些常用的类似枚举的值,比如说 升级丹的 id,在很多地方都要填,如果直接它的道具 id,既不直观,也容易出错。 Luban 支持常量替换。如示例,导出时SHENG_JI_DAN会被替换为11220304。 ``` xml - - + + ``` @@ -880,6 +887,7 @@ xml中定义如下 ||3| 1001| ### 灵活的配置文件组织形式 + 支持以下几种组织形式,允许开发者根据情况灵活组织配置文件结构。例如可以一个表对应一个xlsx文件;可以多个表都放到同个xlsx文件;可以一个表对应多个xlsx文件;可以一个表对应一个目录。 - 来自某个excel文件的所有单元薄 @@ -897,11 +905,13 @@ xml中定义如下 - [yaml](docs/data_yaml.md) ### 多种导出数据格式 + 支持以下几种导出数据格式 + - binary -- protobuf -- msgpack -- flatbuffers +- protobuf (binary、json) +- msgpack (binary) +- flatbuffers (json) - json - lua - erlang @@ -924,20 +934,23 @@ binary格式占空间最小,lua其次,json最大。 [自定义模板](docs/render_template.md) ### 本地化 + 支持以下几种本地化机制,详见[本地化](docs/l10n.md) + - 静态本地化 - 动态本地化 - 多分支数据 - 时间本地化 - [TODO] 任意粒度的数据本地化(不仅仅是text及记录级别) - ## Excel2TextDiff + 将excel文件转成text,再调用diff工具对比。与TortoiseGit、TortoiseSvn等版本管理工具良好配合。 ![pipeline](docs/images/examples/d_70.jpg) -## [LubanAssistant](https://github.com/focus-creative-games/luban_examples/tree/main/Tools/LubanAssistant) Excel插件。神器! +## [LubanAssistant](https://github.com/focus-creative-games/luban_examples/tree/main/Tools/LubanAssistant) Excel插件。神器 + 对于多人协作编辑的配置表,如何以xlsx格式保存配置,很容易出现数据冲突覆盖的问题,在大型项目中尤为严重。另外合并多分支数据时,xlsx无法像文本文件那样自动解决冲突,给项目的版本维护带来很大麻烦。 一个合理的解决思路是,以json、xml之类格式保存配置数据,在excel中编辑。LubanAssistant较好地解决了这个问题,使用者既享受luban强大的数据处理能力、同时拥有json良好的可阅读性及多版本可维护性,还能兼顾excel的便捷的编辑能力。 @@ -945,6 +958,7 @@ binary格式占空间最小,lua其次,json最大。 ![pipeline](docs/images/examples/e_10.jpg) id为1的记录对应的内容如下 + ```json { "id":1, @@ -956,7 +970,6 @@ id为1的记录对应的内容如下 } ``` - ## 代码预览 这儿只简略展示c#、typescript、go语言在开发中的用法,更多语言以及更详细的使用范例和代码见[示例项目](https://github.com/focus-creative-games/luban_examples)。 @@ -986,11 +999,12 @@ console.log(tables.TbItem.get(12).Name) ``` - go 使用示例 + ```go // 一行代码可以加载所有配置。 cfg.Tables 包含所有表的一个实例字段。 if tables , err := cfg.NewTables(loader) ; err != nil { - println(err.Error()) - return + println(err.Error()) + return } // 访问一个单例表 println(tables.TbGlobal.Name) @@ -999,19 +1013,18 @@ println(tables.TbItem.Get(12).Name) ``` - ## 性能测试数据 硬件: - Intel(R) Core i7-10700 @ 2.9G 16核 - 32G 内存 + Intel(R) Core i7-10700 @ 2.9G 16核 + 32G 内存 数据集 - 500个excel表 - 每个表有1000行比较大的记录 - 每个表文件大小 132k + 500个excel表 + 每个表有1000行比较大的记录 + 每个表文件大小 132k 测试结果: @@ -1022,6 +1035,7 @@ println(tables.TbItem.Get(12).Name) | lua | 17.323 s| 739 ms | 433 K | 212 M | ## 路线图 + - [ ] 新增 unity 内置编辑器 - [ ] 新增 unreal 内置编辑器 - [ ] 补充单元测试