函数(Function)是一个可包含多行命令的数据包文件。作为一个文本文件,函数可以很容易地进行修改,并且在执行大量命令时更不容易像命令方块一样造成延迟。
定义[]
函数是一个扩展名为.mcfunction
的文本文件。其编码应为ANSI或无BOM的UTF-8。
在以下结构图中,以黑体着重标识了函数文件所属的数据包目录:
- (数据包名字)
- pack.mcmeta
- pack.png
- data
- (命名空间)
- advancements
- (进度).json
- functions
- (函数).mcfunction
- item_modifiers
- (修饰器).json
- loot_tables
- (战利品表).json
- predicates
- (谓词).json
- 更多文件夹…
- advancements
- (命名空间)
像其他的数据包文件一样,functions
文件夹也能包含若干子文件夹以组织更深的层级关系。在调用这些子文件夹内的函数时,也必须引用子文件夹名。
允许的命令[]
在函数文件中,单个命令的长度不受命令方块字符数上限32,500的限制,但是同一游戏刻运行的总命令数量受/gamerule maxCommandChainLength
的限制(默认为65536)。超过此数量限制的命令将在运行时被忽略。
在单人或局域网世界中,与命令方块一样,函数可以执行任何权限等级不超过2的命令。
在默认的多人游戏,函数要运行的命令的权限等级不能超过设定在server.properties
中的function-permission-level
。
用法[]
要使用函数,首先必须在[世界名称]/datapacks/[数据包名称]/data/[命名空间]/functions
这个顶层文件夹中放置名为[函数名称].mcfunction
文本文档,这个文档将包含此函数内所有需要执行的命令。注意它的编码,以便被Minecraft正常读取。如果是单人游戏,这个世界文件夹可以在.minecraft/saves
中找到;如果是多人游戏,函数必须放置在每一个需要使用这个函数的世界文件夹中。这个顶层文件夹的名字将在调用其中函数时作为其命名空间。
在执行函数时,推荐写为严谨格式[命名空间]:[函数名称]
。如果你可以确认你的函数不和其他现有函数冲突,则可以简写为[函数名称]
,程序将先遍历默认命名空间minecraft:
中的函数名称,再检索其他命名空间。但是为了避免在未来的版本因为Mojang对默认命名空间的改动而导致意料之外的事,最好使用自定义的命名空间并明确地使用它。[1]当然,函数也可以被放置在这个顶层文件夹的子文件夹中。例如,如果需要调用datapacks/[数据包名称]/data/custom/functions/example/test.mcfunction
的函数文件。则需描述为custom:example/test
(相对路径)
如果对函数文件的内容或位置进行了修改,则可以使用/reload
来重新从硬盘加载。这允许Minecraft识别函数文件的更改,而不必重新进入世界。
函数执行成功后将会在聊天栏显示信息:执行了函数[函数名]中的[数量]条命令。函数内部命令的成功与否并不能直接被比较器检测(虽然你还是可以通过/execute
与/scoreboard
来获取这些信息)。
格式[]
在.mcfunction
文件中,每一行都允许一条不带前导正斜杠/
的命令。玩家可以在行首添加#
来注释单行文本。在每条命令的各参数间,不允许添加多个空格,但可以在一条命令的首末位置添加若干制表符和空格。
对于一行命令,如果在末尾使用反斜杠\
,则允许在下一行添加后续部分。后续行的前后两端的空白会被截去,并尝试承接上一行命令。这提供了一种将单行命令拆分为多行书写的方法。
宏[]
通过使用$
开头(作为非空白字符),即可标记此指令为宏指令。宏指令中可包含若干以$(变量)
格式存在的参数。当执行/function (命名空间):函数 <arguments>
命令调用包含宏行的函数时,会以<arguments>
替换其中的参数。<arguments>
中必须包含函数中每一个被调用的参数,但不一定每一个提供的参数都必须被调用,可以包含多余的。若替换后的命令无法解析,则整个函数会被跳过。
例如:
function foo:bar {key_1:"宏指令", key_2:10, key_3:"冗余参数"}
其中foo_bar的内容是:
say 这是一条普通指令 $say 这是一条 $(key_1)! $teleport @s ~ ~$(key_2) ~
调用[]
函数可能以不同的方式从数据包中的其他文件调用。
通过命令[]
可以使用/function
命令调用函数。
一个单独的函数可以通过其命名空间ID来调用。
不像其他的数据包文件,函数被标签支持,这允许它们能合为一组。/function
也接受函数标签的命名空间ID,以便调用一系列函数。
通过进度[]
达成一个进度时,可以运行一个函数作为奖励。函数中命令的执行者是达成进度的玩家。
奖励函数在进度JSON文件中通过以下方式调用:
{
"rewards": {
"function": "命名空间:指向函数文件的路径"
}
}
通过函数标签[]
函数可以通过数据包中的标签组合到一起。标签中的函数将以其定义顺序从上到下依次执行。如果同一函数多次出现,则只在首次出现时执行。
可以通过/function #(命名空间):标签
命令来调用一个函数标签包含的若干函数。
例如:
function #example:example_tag
则调用了example
命名空间下tags/functions
目录中的example_tag.json
文件中列出的所有函数。
另外,在minecraft
命名空间下包含了两个拥有特殊行为的函数标签:
- 在
minecraft:load
标签中列出的函数将在世界加载时或者服务器被启动时执行。每当数据包重载时,这些函数也将被执行。
- 在
minecraft:tick
标签中列出的函数将在每一刻开始时执行。随着游戏刻递增,这些函数将反复执行。
- 在
注:在minecraft:tick
标签中的第一个函数将在minecraft:load
中的函数运行前运行。这意味着,假定minecraft:tick
中依次有tick1
、tick2
、tick3
,minecraft:load
中有load1
,则/reload
后函数的运行顺序为:tick1
、load1
、tick2
、tick3
...
何时被调用[]
函数将在一游戏刻内运行其中的所有命令。同时,如果一个函数是被其他的函数所引用,那么它将同其父函数在同一游戏刻运行。函数会使用函数调用者的命令环境,这包括命令的执行实体,以及执行位置、朝向、维度和基准点。无论函数中的命令的顺序如何,对函数内发生的命令环境的更改都不会影响此函数内(及其子函数内)其他命令使用的命令环境,直到下一次迭代为止。在同一函数内,/execute
命令可以改变当前的命令环境,同时不对之后的任何命令产生影响。
例如:
execute as @a at @s run function foo:bar
其中foo:bar的内容是:
teleport @s ~ ~5 ~
setblock ~ ~-1 ~ minecraft:emerald_block
execute at @s run setblock ~ ~-1 ~ minecraft:diamond_block
这3个命令会将所有玩家向上传送5个方块、在玩家传送前位置的脚下放置绿宝石块,再于玩家传送后位置的脚下放置钻石块。这个特性不会影响到命令中出现的目标选择器参数。
在上例中,命令的环境参数依然将受到其各自的execute
子命令的影响。
历史[]
Java版 | |||||
---|---|---|---|---|---|
1.12 | pre1 | 加入了函数。 | |||
pre3 | 函数中的命令不再允许以/ 开头。
| ||||
现在仅能使用# 来注释,不再允许使用先前的// 。 | |||||
pre4 | 加入了新的参数:[if|unless] [选择器] 。 | ||||
pre6 | 在命令中使用函数时,函数执行被跳过(执行条件不符)的情况现在被视为命令失败。 | ||||
1.13 | 17w43a | 自定义函数被移动至数据包中。 | |||
17w45a | 函数在加载时就会被完全解析与缓存。 | ||||
17w49b | 函数现在可以有标签了。 | ||||
标记了minecraft:tick 的函数现在会在每一个游戏刻的开始时执行。 | |||||
18w01a | 标记了minecraft:load 的函数会在加载(或重新加载)数据包后执行 | ||||
1.20.2 | 23w31a | 现在可使用反斜杠\ 作为行末字符,以便命令在下一行进行承接。
| |||
函数现在可以包括宏行,成为宏函数。 | |||||
pre1 | 现在无论数值的类型如何,作为宏参数使用的数字在插入时都不会包含后缀。 |
参考[]
组件 |
| ||
---|---|---|---|
数据包 | |||
教程 |
|
版本 | |||||||
---|---|---|---|---|---|---|---|
开发周期 |
| ||||||
技术 |
| ||||||
多人游戏 | |||||||
游戏订制 |
语言