第二章小结
本章我们讨论了模块 1:命令在附加包领域的延伸,也就是函数和结构。我们知道函数本质上可以看成是一串无条件执行的命令方块链,所以编程思路上和命令方块是很类似的。但是又由于文件化的编程思路和无条件瞬时完成执行的特点,所以函数又和命令方块编程有一点不同。至于结构,我们主要扩展了如何通过附加包保存结构,以及结构的命名空间等。我们现在来回顾刚讲的内容:
- 函数(Function):是一种用于在被调用时,按顺序执行文件中写入的命令的文件
- 使用函数的优势:可见性强、编辑优势明显、支持更长的注释、空间影响低、支持旧语法等……
- 创建函数
- 在行为包根目录中创建一个名为
functions的文件夹,并在其中创建一个后缀为 .mcfunction 的文件,这就是函数文件
- 执行函数的时候,从上到下依次执行每一行命令,和无条件的 CB 链的执行效果一致,命令的开头不允许带斜杠
- 开头为 # 的一行是注释,不会被读取,注释不能写到命令的后面,实际工程中推荐使用注释增加代码易读性
- 在
functions内部可以创建新的函数文件和文件夹,名字不宜过长
- 在实际工程中,建议引入一个命名空间以防止和其他地图产生冲突
- 在行为包根目录中创建一个名为
- 调用函数
- 函数有 2 种调用方式:使用
/function
命令直接调用、使用/schedule
命令延迟或在特定位置调用 - 函数内命令上下文,取决于是谁调用了这个函数
- 如果是玩家调用的,则命令上下文为玩家的命令上下文
- 如果是服务器调用的(例如
tick.json),则命令上下文为:执行者为空、执行位置为(0, 0, 0),执行朝向为(0, 0),执行维度为主世界
- 如果在测试时,玩家调用函数的效果和服务器调用函数的效果不一致,则可以排查命令上下文相关的问题
- 修改了函数之后,不必小退或大退重新加载函数,只需要使用
/reload
重载函数即可 - 函数可以调用其他函数,符合深度优先原则;调用自身时成为递归(不过这种操作很消耗性能)
- 通过函数最多可以在 1 游戏刻内执行 10000 条命令,这可以通过
/gamerule
来调整 - 通过
tick.json可以每 1 游戏刻执行一次函数,达到循环执行的目的,也可以使得整张地图无 CB 化
- 函数有 2 种调用方式:使用
- 使用合适的工具简化工作
- 灵活使用 VSC 的两个插件,借助自动补全功能编写函数可以大幅减少工作量
- 使用 VSC 打开一整个文件夹,以实现文件之间的协调联动
- 对于 VSC 插件报错的情况,务必不要被其可能出现的错误的报错迷惑,在确信自己是正确的情况下使用“快速修复”的功能忽略错误的检查
- 基于函数的命令系统
- 为了在循环执行的函数中实现单次执行,我们引入了“事件”这个概念。通过循环检测,触发事件型函数,并回调检测条件,就可以做到函数的单次执行。通常,事件型函数是单独列出的,并在习惯上可以放在
events里表示一个事件,例如
player_join.mcfunction可以代表玩家重进游戏,在玩家进入游戏时执行;
player_die.mcfunction可以代表玩家死亡,在玩家死亡时执行等等。
- 为了在无条件瞬时执行的函数中实现有条件延时执行,我们引入了“时间线”这个概念。通过引入这样一个延时执行的计时系统,我们可以规定什么时候执行什么命令。通常,要执行这些时间线对应的函数也是带有条件的,所以这种逻辑很适合特定关卡的循环逻辑。
- 为了快捷高效地执行大量重复应用的代码,我们引入了“库函数”这个概念。通过引入这样一类函数,我们可以快捷地调用一个函数来执行一长串逻辑,而且更改这个逻辑可以方便地使全局生效。
- 内容日志:排查附加包问题的一种基本手段。可以用于排查命令语法错误等,需要在设置中启用。
- 为了在循环执行的函数中实现单次执行,我们引入了“事件”这个概念。通过循环检测,触发事件型函数,并回调检测条件,就可以做到函数的单次执行。通常,事件型函数是单独列出的,并在习惯上可以放在
- 旧版本函数:通过更改
manifest.json的
min_engine_version
来使用旧语法。当然,如果你在编写函数的过程中发现无法使用新语法,则为min_engine_version
调的过低的结果,建议至少也要调到网易当前所对应的版本。 - 附加包中的结构:我们将结构文件放到行为包的
structures -
(命名空间)的文件夹里,并使用
(命名空间):(结构名)
来调用这个结构。