MC数据包接口示范

gamersky_01small_02_2016926109e27

引言
本规范希望能透过定义部分规定,让数据包作者共同遵守,最终能编写可读性及扩展性更高的数据包。
本规范主要针对希望开放接口供其他数据包使用,以及希望使用其他数据包接口的数据包。
为了方便统一管理模块,本规范会同时提供一个 std 模块,实现部分单一模块较为困难实现的功能。

名词定义
为了方便,本文将会先定义一些名词,以免过于累赘。

  • 模块: 数据包内的不同目录(文件夹),但不包括如tags, functions等定义内部文件种类的目录。
  • 重构: 即改变数据包架构,如改变模块名称、把部分命令移到别的函数内的行为。
  • 内部函数: 即该命令函数的实际内容。为了只在某条件下运行那命令函数,而把实际内容移至别的命令函数,并把命令函数内容改为 execute (条件检查) run function 内部函数。

命名、结构规范
所有模块、命令函数等的名称,应遵从snake_case的要求,单词之间以_分开。如需序号亦应在序号后加上_分开,以免混淆。

  (如 2_json 与 2json 意思有所不同。前者为序号。后者的2能解读为to,即变为,的意思)

命名空间可加上作者标识_前缀,可以为组织名称。以避免发生命名冲突。所有命名空间名称应长于4个字符,并且应避免与现有mod、其他数据包的命名空间出现冲突。(它们都是使用这个系统,出现冲突可能带来未知影响。)
单一数据包只应有一个命名空间,其他命名空间只应该用作处理命令函数标签、接口实现等事情。

  • 需要在高频运行的命令函数(主函数,一个模块只可有一个,不包括子模块)应命名为 tick。如无依赖则应加上 std:tick 标签。
  • 应最先运行的命令函数(系统状态改变时)应命名为 init。
  • 需要在数据包加载时运行的命令函数应放在 _init 模块内,放在命名空间之下。
  • 在移除数据包时执行的命令函数应命名为 (命名空间):delete。

数据包加载、移除

加载执行命令
每个数据包加载时应先执行如下命令:

  1. # 宣示成功加载:
  2. scoreboard players set #(命名空间) common 0
  3. # 宣示实现的接口
  4. scoreboard players set #(接口定义的假名) common 0
  5. # 其他命令...

复制代码

加载方式
没有依赖:使用 std:load 标签。(std:load之前会定义common这个记分板变量供其他数据包作数据包沟通使用)
当数据包出现加载依赖时,如b需要在a之后加载(常见于接口使用)。以下假设它们的命名空间分别为b和a。

  • a应定义一个命令函数标签,名为 (a):dependents,在a加载后(执行完a的_init模块内的函数后)执行那标签的命令函数。基本上所有打算开放接口的数据包都应该定义这个标签,其命名空间应避免和其他模块产生冲突。
  • 而b的_init模块内的命令函数应加上(a):dependents 标签,不应加上std:load 标签。

如需使用 std 数据包里的库,直接调用 std:(库)/init 即可,std:load保证了 std 数据包必定在此命令函数执行前加载完毕。

卸载数据包
除了地图专用 (map-specific) 的数据包以外,其他数据包应定义 (命名空间):delete 以供移除相关资料,并调用 #(命名空间):delete以移除依赖其的数据包。其子模块亦应提供删除用命令函数,并加上 (依赖数据包命名空间):delete 标签,以在依赖模块被删除时一并删除。

检测成功加载
数据包应包含 (命名空间):check 函数以检测其有否正确加载,以及其需要的接口有没有被实现。此命令函数应加上 std:check 标签。
例子:

  1. # foo:check
  2. # 如果#foo不为0则代表有部分检查出现错误,之后tick的模块应该检查这分数决定应否执行。
  3. execute unless score #foo common matches 0 run say 数据包foo未能正确加载!
  4. # 检查接口,发现问题则设置 #foo common 分数为1。如果#foo common分数不为1则不用检查,因为已经出问题了。
  5. execute if score #foo common matches 0 store result score #foo common unless score #foo_interface1 common matches 0 run 数据包foo的接口 interface1 没有被实现!
  6. # 检查依赖函数(不是加载依赖,故此可独立加载,需要检测),发现问题则设置 #foo common 分数为1。如果#foo common分数不为1则不用检查,因为已经出问题了。
  7. execite if score #foo common matches 0 store result score #foo common unless score #std_rnd common matches 0 run 数据包std的rnd模组未能加载!数据包foo不能使用!

复制代码

所有拥有 std:check 标签的命令函数都会在加载后第一游戏刻运行一次,早于第一个 std:tick 执行。

  注:使用std:check 不是依赖于std数据包。

接口

接口类型

  • 调用外部系统
    • 命令函数:需要外部系统提供一个命令函数以达到指定功能。一般为地图专用数据包用接口。
    • 命令函数标签:提供给外部系统聆听事件以作出处理。聆听此事件(拥有此标签)的命令函数可以多于一个

        注意: 标签文件禁止使用 "replace":true,因为这样会影响到其他模块。
      使用命令函数标签时应定义一个假名,被调用的函数只应在那假名为指定分数时执行(调用内部函数)。如需阻止之后其他函数执行,则可以更改那假名数值。如1为能够执行,0为不能执行。

  • 提供于外部系统
    • 函数:传入分数,执行后回传处理后的分数或根据传入分数进行操作。

        注意:没人能保证传入的分数不会被改变。
      建议使用 common 记分板变量,传入分数假名建议为 #param, #param1...,而回传分数假名建议为 #result, #result1...

  • 其他,请参考实际数据包文档决定如何使用。
    • 实体标记(marker)
    • 记分板假名(fake player name)

发表评论

您必须 登录 才能发表留言!