前言

最近有几个其他项目组的童鞋给我之前的 转表工具链-xresloader 提了几个需求。然后我也根据我们近期一些需求点对转表工具链一起给这套工具做了点功能增强和细节上的一些改进。 这篇blog差不多是这些东西的 CHANGELOG了吧。

插件和协议和CI

对一些复杂的需求,使用protobuf插件机制比配置在excel里描述能力要强的多。所以近期大多的新功能都是由插件配置的。但是以前 转表引擎-xresloader 的发布流程里只包含输出的jar,协议得去对应源码包里找。另外一个童鞋报给我说找 github 的release里的源码包似乎并不支持git lfs,解出来的git lfs文件只有一个版本号,所以我给CI的发布流程里加了对应版本的protocol文件的打包,当然也包括插件的protocol。

然后顺便也修复了 sample 里的 powershell 脚本,现在有 powershell-core 的情况下。跨平台脚本反而 powershell-core 能比较统一了。 原来的是直接bash脚本copy来稍微改了下,兼容性也是有点问题。

转表引擎-xresloader 的新增功能

  • 数字类型转字符串,使用 %g 格式(去除不必要的小数点和0)

这个主要是之前如果Excel里配置了数值类型,而协议里配置的是文本的话,由于Excel里接口读取出来只有浮点类型,对0而言,直接的同String接口会返回 0.0 。所以就对浮点数值转字符串特别处理了下。让它不再写出无用的后缀。

  • 常量导出现在会导出protobuf的message里包含oneof了 (使用C++的命名规则 k大写驼峰名字)

我们自己的项目里现在会使用oneof做一些优化,然后偶尔也会使用一些内嵌的美剧类型。原先常量到处功能导出的枚举和oneof只导出了file层面的枚举,并没有导出oneof。为了方便我们客户端lua层和Web的GM工具的js方便访问,加入了这个内嵌message的oneof和枚举的常量导出。由于oneof没有官方的名称接口,所以我这里导出用了C++里的命名规则了。

  • 支持解析protobuf的内嵌message

这个是和上面的一起的,然后协议映射也支持配置成内置message了。这个是顺便做的估计没啥需求。

  • 增加protobuf插件 - org.xresloader.field_alias 可以设置字段别名并用于配置了验证器的excel数据中

这条是其他项目组提的需求,他们希望直接excel里配中文名,但是转表的时候转回枚举类型对应的整数。但是不希望走macro表,因为这样就会把很多枚举的内容混在一起。这个需求我们以前的解决方案是直接配字段的名字( 文档: https://xresloader.atframe.work/zh_CN/latest/users/advance_usage.html#id4 ),这个中文别名的功能之前没想到什么维护方便和自动化程度高的方式。也是因为那时候 xresloader 还没有支持protobuf的插件扩展。现在可以通过protobuf插件机制支持了。但是也是得使用方导入 xresloader 的插件proto 。

  • 增加protobuf插件 - org.xresloader.enum_alias 可以设置枚举项目的别名并用于配置了验证器的excel数据中

这条和上面一样,只是上面那条是针对message里的field的,这个是针对enum的。

  • 增加protobuf插件 - org.xresloader.field_ratio 可以设置字段放大倍数值,可用于需要转出整数类型的百分率/千分率/万分率,但excel中保留小数表达

这条是起源于我们项目组的一个需求,就是方便策划配表。我们战斗引擎里是不都是整数,没有浮点数,但是又希望方便策划配置千分率的时候对于 35% 可以配置成 0.35 。但是转出千分率的时候导出 350, 现在这里 字段上配置 org.xresloader.field_ratio 就行了。

批量转表工具之 xresconv-cli 和 xresconv-gui 的新增功能

xresconv-cli

  1. 支持多个 <output_type></output_type> 参数,支持给每个 output_type 单独设置 rename 规则;

    这也是其他项目组提的一个需求,他们是希望转出程序的二进制的同时可以直接也输出一个其他格式的可读的文本配置。本来是想加到 xresloader 里,可能还可以复用里面的 AST 的。但是后面想起来没办法复用AST,因为那个和Excel的列映射相关。如果要支持配置多个DataSource,这种情况必然要重建AST。如果流程保持一致的话这两个功能是冲突的。现阶段 xresloader 性能还比较好,所以暂时不想为了这一个需求增加代码维护的复杂性。所以加入到批量导表的协议规范里了。

  2. 优化标准输出和标准错误的输出编码,自动转换 xresloader 的输出编码;

    之前试过一些方式让 xresconv-cli 去适配各种环境的终端编码,但是python2+python3,linux+macOS+Windows+MinGW+Cmd(cp936)+Cmd(cp65001)+Powershell(GBK)+Powershell(UTF-8)+Powershell-core,总没发现万金油。现在换了一种实现,在python层转一次编码。看看效果吧。

  3. 优化 xresloader 的输入编码;

xresconv-gui

  1. 支持多个 <output_type></output_type> 参数,支持给每个 output_type 单独设置 rename 规则

    和上面 xresconv-cli 一致的接入

  2. set_name 事件增加 alert_warning(text)/alert_error(text)/log_info(text)/log_error(text) 函数

  3. set_name 事件增加 work_dir 变量和 configure_file 变量

  4. on_before_convert/on_after_convert 事件增加 configure_file 变量

  5. 采用Promise重构建立节点树的的流程

  6. 更新依赖库

为了更方便 xresconv-gui 的事件里读取构建信息的数据和控制GUI的log,补了一些函数和事件,现在的各类接口和事件的可用变量描述如下(新增的标记了 要求版本>=2.2.0 ):

set_name 事件数据。

{
    work_dir: "工作目录(要求版本>=2.2.0)",
    configure_file: "载入的配置文件路径(要求版本>=2.2.0)",
    item_data: {
        id: "条目ID",
        file: "数据源文件",
        scheme: "数据源scheme表名",
        name: "描述名称",
        cat: "分类名称",
        options: ["额外选项"],
        desc: "描述信息",
        scheme_data: {"元数据Key": "元数据Value"}
    },
    alert_warning: function(content, title, options) {},    // (要求版本>=2.2.0) 警告弹框, options 结构是 {yes: 点击是按钮回调, no: 点击否按钮回调, on_close: 关闭后回调}
    alert_error: function(content, title) {},               // (要求版本>=2.2.0) 错误弹框
    log_info: function (content) {},                        // (要求版本>=2.2.0) 打印info日志
    log_error: function (content) {}                        // (要求版本>=2.2.0) 打印info日志
}

on_before_convert/on_after_convert 事件数据。

{
    work_dir: "执行xresloader的工作目录",
    configure_file: "载入的配置文件路径(要求版本>=2.2.0)",
    xresloader_path: "xresloader目录",
    global_options: {"全局选项": "VALUE"},
    selected_nodes: ["选中要执行转表的节点集合"],
    run_seq: "执行序号",
    alert_warning: function(content, title, options) {},    // 警告弹框, options 结构是 {yes: 点击是按钮回调, no: 点击否按钮回调, on_close: 关闭后回调}
    alert_error: function(content, title) {},               // 错误弹框
    log_info: function (content) {},                        // 打印info日志
    log_error: function (content) {},                       // 打印info日志
    resolve: function (value) {},                           // 通知上层执行结束,相当于Promise的resolve
    reject: function(reason) {},                            // 通知上层执行失败,相当于Promise的reject
    require: function (name) {}                             // 相当于 nodejs的 require(name) 用于导入nodejs 模块
}