本篇教程由作者设定使用 CC BY-NC-SA 协议。
(CNC1.3.6及以前,数据包内示例函数有一些小错误,在CNC1.3.X fix1中修复,请注意)
有序合成
这是一个有序合成的示例函数:
execute if block ~ ~ ~ minecraft:barrel{Items:[{Slot:20b,id:"minecraft:stick",tag:{CNC_example:0b}},{Slot:11b,id:"minecraft:stick"},{Slot:1b,id:"minecraft:iron_ingot"},{Slot:2b,id:"minecraft:iron_ingot"},{Slot:10b,id:"minecraft:iron_ingot"}]} if entity @s[scores={CNC_table_count=5}] run item replace block ~ ~ ~ container.16 with minecraft:iron_axe{Output:1b,CNC_example:1b }
它表示在合成区如下放置物品:
铁锭 | 铁锭 | |
铁锭 | 木棍 | |
木棍* |
*带有{CNC_example:0b}标签的木棍
时,输出栏输出带有{CNC_example:1b}标签的铁斧。
操作注意事项:
1、 在if block字段下,barrel的NBT里填写合成区摆放的物品,Item列表下,每一个对象是一个物品。其中需写明物品id、NBT标签(即tag,如有)和槽位(即Slot。合成区槽位:由上到下,由左到右依次为:1b,2b,3b;10b,11b,12b;19b,20b,21b)
2、 在if entity字段下的CNC_table_count计分板填写放入合成区的物品一共占用了几个槽位(这一个条件是为了防止多放入物品而设置);
3、 在 item replace 字段下填写输出物品数据,和give命令的格式相同;
4、 但需要在输出物品下添加{Output:1b}的标签,否则不能正常工作。
5、 如果你的配方支持平移或镜像合成,你需要将平移或镜像后的配方按新的槽位位置再写一遍,即需要穷举所有可能情况。
无序合成
无重复物品的无序合成
无序合成的语法与有序合成相同,唯一的区别在于填写合成区物品时不写Slot标签;
因此,有序合成和无序合成可以混用,你可以指定部分物品按指定方式排列,而另一部分物品随意排列。
以下是末影之眼的完整示例:
execute if block ~ ~ ~ minecraft:barrel{Items:[{id:"minecraft:blaze_powder"},{id:"minecraft:ender_pearl"}]} if entity @s[scores={CNC_table_count=2}] run item replace block ~ ~ ~ container.16 with ender_eye
有重复物品的无序合成
因为在if里填入多个相同对象不会让数据包检测多个物品,只要有一个这样的物品就会通过这个条件,所以对于有重复物品的无序合成配方,需要用计分板方法辅助判定。
在主要命令前加入以下命令:
execute store result score @s CNC_SLout if data block ~ ~ ~ Items[{id:"minecraft:paper"}]
计分板CNC_SLout是预设的无序合成判定用的计分板,你可以换成自己的,只要上下一致,没有关系。
在下面的主函数中,在if entity字段后的条件中加入CNC_SLout的计分板,其分数为该物品的个数:
execute if block ~ ~ ~ minecraft:barrel{Items:[{id:"minecraft:paper"},{id:"minecraft:leather"}]} if entity @s[scores={CNC_table_count=4,CNC_SLout=3}] run item replace block ~ ~ ~ container.16 with book{Output:1b}
对于有多种重复物品的无序合成,使用多个计分板,如法炮制即可。
已预设的计分板有:CNC_SLout,CNC_SLout2,CNC_SLout3,CNC_SLout4
以下是书的合成的完整示例:
#无序合成模块
execute store result score @s CNC_SLout if data block ~ ~ ~ Items[{id:"minecraft:paper"}]
#主命令
execute if block ~ ~ ~ minecraft:barrel{Items:[{id:"minecraft:paper"},{id:"minecraft:leather"}]} if entity @s[scores={CNC_table_count=4,CNC_SLout=3}] run item replace block ~ ~ ~ container.16 with book{Output:1b}
替换合成栏物品(需要版本1.4及以上)
替换合成栏物品:有时合成物品后,合成栏内部分物品不需要清除,只需要将其替换为其他物品或不作改动。
此时可以用以下方法实现:主函数结束后检测输出栏物品,若为本配方的目标物品,则将对应合成栏位的计分板(CNC_replace_1~9,见下例)设置为指定值,该值需要在cnc/funcctions/machine/crafting_table/recipes/clear/replacements.mcfunction文件中建立对应,操作方法见对应函数中的示例。
已有的预设:0为不动(没有建立对应的值都是不动),1为替换成桶(适用于水桶、熔岩桶、牛奶桶),2为空瓶(处理较为特殊,适用于药水、蜂蜜瓶)
若该槽位物品数量大于1(如堆叠了多个蜂蜜瓶),则向玩家返还一个被替换的物品,同时合成栏槽位物品数量减1,;若数量等于1,则将该槽位物品替换为指定物品。
示例1:蛋糕的合成
#主命令
execute if block ~ ~ ~ minecraft:barrel{Items:[{Slot:1b,id:"minecraft:milk_bucket"},{Slot:2b,id:"minecraft:milk_bucket"},{Slot:3b,id:"minecraft:milk_bucket"},{Slot:10b,id:"minecraft:sugar"},{Slot:12b,id:"minecraft:sugar"},{Slot:11b,id:"minecraft:egg"},{Slot:19b,id:"minecraft:wheat"},{Slot:20b,id:"minecraft:wheat"},{Slot:21b,id:"minecraft:wheat"}]} if entity @s[scores={CNC_table_count=9}] run item replace block ~ ~ ~ container.16 with minecraft:cake{Output:1b}
#检测替换
execute if block ~ ~ ~ minecraft:barrel{Items:[{Slot:16b,id:"minecraft:cake"}]} run scoreboard players set @s CNC_replace_1 1
execute if block ~ ~ ~ minecraft:barrel{Items:[{Slot:16b,id:"minecraft:cake"}]} run scoreboard players set @s CNC_replace_2 1
execute if block ~ ~ ~ minecraft:barrel{Items:[{Slot:16b,id:"minecraft:cake"}]} run scoreboard players set @s CNC_replace_3 1
如果要替换的物品没有确定的槽位,则需要穷举检测其槽位。
示例2:由蜂蜜合成糖
#主命令
execute if block ~ ~ ~ minecraft:barrel{Items:[{id:"minecraft:honey_bottle"}]} if entity @s[scores={CNC_table_count=1}] run item replace block ~ ~ ~ container.16 with minecraft:sugar{Output:1b} 3
#检测替换
execute if block ~ ~ ~ minecraft:barrel{Items:[{Slot:16b,id:"minecraft:sugar"},{Slot:1b,id:"minecraft:honey_bottle"}]} run scoreboard players set @s CNC_replace_1 2
execute if block ~ ~ ~ minecraft:barrel{Items:[{Slot:16b,id:"minecraft:sugar"},{Slot:2b,id:"minecraft:honey_bottle"}]} run scoreboard players set @s CNC_replace_2 2
execute if block ~ ~ ~ minecraft:barrel{Items:[{Slot:16b,id:"minecraft:sugar"},{Slot:3b,id:"minecraft:honey_bottle"}]} run scoreboard players set @s CNC_replace_3 2
execute if block ~ ~ ~ minecraft:barrel{Items:[{Slot:16b,id:"minecraft:sugar"},{Slot:10b,id:"minecraft:honey_bottle"}]} run scoreboard players set @s CNC_replace_4 2
execute if block ~ ~ ~ minecraft:barrel{Items:[{Slot:16b,id:"minecraft:sugar"},{Slot:11b,id:"minecraft:honey_bottle"}]} run scoreboard players set @s CNC_replace_5 2
execute if block ~ ~ ~ minecraft:barrel{Items:[{Slot:16b,id:"minecraft:sugar"},{Slot:12b,id:"minecraft:honey_bottle"}]} run scoreboard players set @s CNC_replace_6 2
execute if block ~ ~ ~ minecraft:barrel{Items:[{Slot:16b,id:"minecraft:sugar"},{Slot:19b,id:"minecraft:honey_bottle"}]} run scoreboard players set @s CNC_replace_7 2
execute if block ~ ~ ~ minecraft:barrel{Items:[{Slot:16b,id:"minecraft:sugar"},{Slot:20b,id:"minecraft:honey_bottle"}]} run scoreboard players set @s CNC_replace_8 2
execute if block ~ ~ ~ minecraft:barrel{Items:[{Slot:16b,id:"minecraft:sugar"},{Slot:21b,id:"minecraft:honey_bottle"}]} run scoreboard players set @s CNC_replace_9 2
包含tag的配方(版本1.3.7及以上)
1.3.7版本及以上支持此方法。
在旧版的基础上稍微简化了操作,但是对性能消耗较大。
首先断言文件的写法稍有不同:
{
"condition": "minecraft:inverted",
"term": {
"condition": "minecraft:alternative",
"terms": [
{
"condition": "minecraft:inverted",
"term": {
"condition": "minecraft:entity_properties",
"entity": "this",
"predicate": {
"equipment": {
"chest": {
"tag": "minecraft:planks"
}
}
}
}
},
{
"condition": "minecraft:inverted",
"term": {
"condition": "minecraft:entity_scores",
"entity": "this",
"scores": {
"CNC_tag_id":-1
}
}
}
]
}
}
使用与门的写法写一个 同时满足分数和物品tag 的条件,建议复制示例断言,记得更改id数值(CNC_tag_id计分板)
然后将此断言引用到主断言中(路径为data/cnc/predicates/crafting_table/tag_main.mcfunction)
主断言中已有一些示例:
{
"condition": "minecraft:alternative",
"terms": [
{
"condition": "minecraft:reference",
"name": "cnc:crafting_table/planks"
},
{
"condition": "minecraft:reference",
"name": "cnc:crafting_table/slabs"
}
]
}
再在配方函数中引用。注意先将CNC_tag_id计分板设为你设置的id值
检测完成后将会将得到的结果记录在盔甲架的CNC_craftag计分板上,以便进一步处理
示例1:碗的合成
#初始化
scoreboard players reset @s CNC_tag_out
scoreboard players reset @s CNC_craftag
#设置id(该id应与你设置的断言文件指定的id一致)
scoreboard players set @s CNC_tag_id -1
#tag检测
#设置CNC_tag_slot为0,检测全部槽位
scoreboard players set @s CNC_tag_slot 0
function cnc:machine/crafting_table/tag
execute if score @s CNC_craftag matches 3 run scoreboard players set @s CNC_tag_out 1
#主命令
execute if block ~ ~ ~ minecraft:barrel{Items:[{Slot:1b},{Slot:11b},{Slot:3b}]} if entity @s[scores={CNC_table_count=3,CNC_tag_out=1}] run item replace block ~ ~ ~ container.16 with bowl
execute if block ~ ~ ~ minecraft:barrel{Items:[{Slot:10b},{Slot:20b},{Slot:12b}]} if entity @s[scores={CNC_table_count=3,CNC_tag_out=1}] run item replace block ~ ~ ~ container.16 with bowl{Output:1b}
对多个tag检测与只对部分槽位检测,使用旧版方法穷举是性能上最佳的方法,见tag_old函数;
如果觉得穷举法较为困难难以掌握,CNC支持一种操作上较为简便,但性能消耗较大的方法:
对多个槽位检测,先检测一个tag,将得到的分数转存在一个计分板上,(CNC提供9个计分板预设:CNC_tag_out计分板,及CNC_tag_out2~9 这8个计分板)然后检测另一个tag,将得到的分数转存在另一个计分板上,然后在主函数中调用这两个计分板的分数即可;(示例中使用一种“开关”的方法,即预先判断返回值是否符合预期,若是则将CNC_tag_out设置为1;当然直接储存返回值再在主函数中判定亦可);
注意检测每个tag前都需要初始化。
只对部分槽位检测,需要设置CNC_tag_slot分数,按照二进制计算(第一个槽位为1,第二个为2,第三个为4,以此类推,最后加在一起)
#如果要检测全部槽位,建议将该值设为0而不是511。
示例2:木桶的合成
#tag检测
#检测木板(槽位:1+3+4+6+7+9,数值1+4+8+32+64+256=365)
scoreboard players reset @s CNC_craftag
scoreboard players reset @s CNC_tag_out
scoreboard players set @s CNC_tag_id -1
scoreboard players set @s CNC_tag_slot 365
function cnc:machine/crafting_table/tag
execute if score @s CNC_craftag matches 6 run scoreboard players set @s CNC_tag_out 1
#检测台阶(槽位:2+8,数值2+128=130)
scoreboard players reset @s CNC_craftag
scoreboard players reset @s CNC_tag_out2
scoreboard players set @s CNC_tag_id -2
scoreboard players set @s CNC_tag_slot 130
function cnc:machine/crafting_table/tag
execute if score @s CNC_craftag matches 2 run scoreboard players set @s CNC_tag_out2 1
#主命令
execute if entity @s[scores={CNC_table_count=8,CNC_tag_out=1,CNC_tag_out2=1}] run item replace block ~ ~ ~ container.16 with barrel{Output:1b}
旧版tag检测方式依然可用,见下方:
包含tag的配方_旧版(所有已发布CNC版本均可用)
操作方法较为复杂。
首先设置断言:
{
"condition": "minecraft:entity_properties",
"entity": "this",
"predicate": {
"equipment": {
"chest": {
"tag": "minecraft:planks"
}
}
}
}
物品在此tag中,断言通过。
然后在函数中引用该断言。
建议先复制下面这段命令(CNC1.3.6及以前,数据包内示例函数中的这一段是有误的,计分板应该是CNC_craftag而不是CAM_craftag,在CNC1.3.X fix1中修复):
#初始化
scoreboard players reset @s CNC_craftag
#检测tag
data modify entity @s ArmorItems[2] set value {id:"minecraft:stone",Count:1b}
data modify entity @s ArmorItems[2].id set from block ~ ~ ~ Items[{Slot:1b}].id
execute if entity @s[predicate=cnc:crafting_table/planks] run scoreboard players add @s CNC_craftag 1
data modify entity @s ArmorItems[2] set value {id:"minecraft:stone",Count:1b}
data modify entity @s ArmorItems[2].id set from block ~ ~ ~ Items[{Slot:2b}].id
execute if entity @s[predicate=cnc:crafting_table/planks] run scoreboard players add @s CNC_craftag 1
data modify entity @s ArmorItems[2] set value {id:"minecraft:stone",Count:1b}
data modify entity @s ArmorItems[2].id set from block ~ ~ ~ Items[{Slot:3b}].id
execute if entity @s[predicate=cnc:crafting_table/planks] run scoreboard players add @s CNC_craftag 1
data modify entity @s ArmorItems[2] set value {id:"minecraft:stone",Count:1b}
data modify entity @s ArmorItems[2].id set from block ~ ~ ~ Items[{Slot:10b}].id
execute if entity @s[predicate=cnc:crafting_table/planks] run scoreboard players add @s CNC_craftag 1
data modify entity @s ArmorItems[2] set value {id:"minecraft:stone",Count:1b}
data modify entity @s ArmorItems[2].id set from block ~ ~ ~ Items[{Slot:11b}].id
execute if entity @s[predicate=cnc:crafting_table/planks] run scoreboard players add @s CNC_craftag 1
data modify entity @s ArmorItems[2] set value {id:"minecraft:stone",Count:1b}
data modify entity @s ArmorItems[2].id set from block ~ ~ ~ Items[{Slot:12b}].id
execute if entity @s[predicate=cnc:crafting_table/planks] run scoreboard players add @s CNC_craftag 1
data modify entity @s ArmorItems[2] set value {id:"minecraft:stone",Count:1b}
data modify entity @s ArmorItems[2].id set from block ~ ~ ~ Items[{Slot:19b}].id
execute if entity @s[predicate=cnc:crafting_table/planks] run scoreboard players add @s CNC_craftag 1
data modify entity @s ArmorItems[2] set value {id:"minecraft:stone",Count:1b}
data modify entity @s ArmorItems[2].id set from block ~ ~ ~ Items[{Slot:20b}].id
execute if entity @s[predicate=cnc:crafting_table/planks] run scoreboard players add @s CNC_craftag 1
data modify entity @s ArmorItems[2] set value {id:"minecraft:stone",Count:1b}
data modify entity @s ArmorItems[2].id set from block ~ ~ ~ Items[{Slot:21b}].id
execute if entity @s[predicate=cnc:crafting_table/planks] run scoreboard players add @s CNC_craftag 1
可以看到,在#检测tag下面,有9组命令,每组3行,这是对9个合成栏槽位进行穷举。
在每组的第三行引用了断言文件(if entity @s[predicate=cnc:crafting_table/planks]),将predicate后面的断言路径改成你自己的断言路径即可。
接下来在配方主函数中,如果是无序合成,则if block字段中不需填写tag物品的相关消息;如果是有序合成,则需要填写tag物品的槽位。注意不要写id。
然后在if entity字段中加入CNC_craftag计分板的分数,即tag物品的总数即可。以下是碗的合成的完整示例:
#初始化
scoreboard players reset @s CNC_craftag
#检测tag
data modify entity @s ArmorItems[2] set value {id:"minecraft:stone",Count:1b}
data modify entity @s ArmorItems[2].id set from block ~ ~ ~ Items[{Slot:1b}].id
execute if entity @s[predicate=cnc:crafting_table/planks] run scoreboard players add @s CNC_craftag 1
data modify entity @s ArmorItems[2] set value {id:"minecraft:stone",Count:1b}
data modify entity @s ArmorItems[2].id set from block ~ ~ ~ Items[{Slot:2b}].id
execute if entity @s[predicate=cnc:crafting_table/planks] run scoreboard players add @s CNC_craftag 1
data modify entity @s ArmorItems[2] set value {id:"minecraft:stone",Count:1b}
data modify entity @s ArmorItems[2].id set from block ~ ~ ~ Items[{Slot:3b}].id
execute if entity @s[predicate=cnc:crafting_table/planks] run scoreboard players add @s CNC_craftag 1
data modify entity @s ArmorItems[2] set value {id:"minecraft:stone",Count:1b}
data modify entity @s ArmorItems[2].id set from block ~ ~ ~ Items[{Slot:10b}].id
execute if entity @s[predicate=cnc:crafting_table/planks] run scoreboard players add @s CNC_craftag 1
data modify entity @s ArmorItems[2] set value {id:"minecraft:stone",Count:1b}
data modify entity @s ArmorItems[2].id set from block ~ ~ ~ Items[{Slot:11b}].id
execute if entity @s[predicate=cnc:crafting_table/planks] run scoreboard players add @s CNC_craftag 1
data modify entity @s ArmorItems[2] set value {id:"minecraft:stone",Count:1b}
data modify entity @s ArmorItems[2].id set from block ~ ~ ~ Items[{Slot:12b}].id
execute if entity @s[predicate=cnc:crafting_table/planks] run scoreboard players add @s CNC_craftag 1
data modify entity @s ArmorItems[2] set value {id:"minecraft:stone",Count:1b}
data modify entity @s ArmorItems[2].id set from block ~ ~ ~ Items[{Slot:19b}].id
execute if entity @s[predicate=cnc:crafting_table/planks] run scoreboard players add @s CNC_craftag 1
data modify entity @s ArmorItems[2] set value {id:"minecraft:stone",Count:1b}
data modify entity @s ArmorItems[2].id set from block ~ ~ ~ Items[{Slot:20b}].id
execute if entity @s[predicate=cnc:crafting_table/planks] run scoreboard players add @s CNC_craftag 1
data modify entity @s ArmorItems[2] set value {id:"minecraft:stone",Count:1b}
data modify entity @s ArmorItems[2].id set from block ~ ~ ~ Items[{Slot:21b}].id
execute if entity @s[predicate=cnc:crafting_table/planks] run scoreboard players add @s CNC_craftag 1
#主命令
execute if block ~ ~ ~ minecraft:barrel{Items:[{Slot:1b},{Slot:11b},{Slot:3b}]} if entity @s[scores={CNC_table_count=3,CNC_craftag=3}] run item replace block ~ ~ ~ container.16 with bowl{Output:1b}
execute if block ~ ~ ~ minecraft:barrel{Items:[{Slot:10b},{Slot:20b},{Slot:12b}]} if entity @s[scores={CNC_table_count=3,CNC_craftag=3}] run item replace block ~ ~ ~ container.16 with bowl{Output:1b}