【补档】从零开始制作一个矿石作物 Addon
本文最初于2022年4月17日发布于在 MCBBS,但由于 MCBBS 因不可抗力关站,特此补档
本篇教程并不是完整的附加包开发教程,仅包括了与完成“矿石作物”这个目标相关的内容,学习更多内容请访问官方文档
本文中提到的一些内容在你阅读的时候可能已经过时,请以官方文档为准
本文若有错误,欢迎在评论区指出,不胜感激
你将学到...
- 自定义物品
- 自定义方块
- 自定义合成配方
- 自定义战利品表
- 本地化
- 一点点 Molang
一切开始前...
- 准备需要使用到的纹理(图标、种子的纹理、作物方块不同生长阶段的纹理等)
- 准备一个文本编辑器
- 安装 Blockbench,你可以在这里下载
- 别忘了最重要的 —— Minecraft 基岩版
准备就绪
开始的开始
你可以按照下面的目录树创建这些在后续需要用到的文件夹
BP是行为包(Behavior Pack)的缩写,\BP
目录则是我们的行为包部分
RP是资源包(Resource Pack)的缩写,\RP
目录则是我们的资源包部分
HelloWorld
├─BP
│ ├─blocks
│ ├─items
│ ├─loot_tables │├─loot_tables
│ └─recipes
└─RP
├─models
│ └─entity
├─texts
└─textures
├─blocks
└─items
清单文件 manifest.json
首先我们需要在 \BP
与 \RP
目录下分别创建一个名叫 manifest.json
的文件
HelloWorld
├─BP
│ ├─...
│ └─manifest.json
└─RP
├─...
└─manifest.json
manifest.json 的基本构成
名称 | 描述 |
---|---|
format_version | 告诉 Minecraft 需要用什么版本来解析这个 Json |
header | 清单的头部信息 |
modules | 此附加包所拥有的模块 |
dependencies | 此附加包的依赖项 |
header
header
所需要包含的头部信息:
名称 | 数据类型 | 描述 |
---|---|---|
name | 字符串 | 此附加包的名称 |
version | 向量 [a, b, c] | 此附加包的版本号 |
min_engine_version | 向量 [a, b, c] | 此附加包所兼容的 Minecraft 的最低版本 |
uuid | 字符串 | 此附加包的标识 |
我们直接把包名设置为 Ore Crops 好了,后面加上 BP、RP 加以区分(事实上不这么做也可以)
描述中我们可以写上作者信息之类的东西
版本号设置成 0.0.1
[注意:若要将附加包上传至基岩版市场,a
值需要大于 0
]
uuid
将作为区分附加包的标识,我们需要设置一个独一无二的,你可以在这个网站在线生成 uuid
modules
modules
所需要包含的内容:
名称 | 数据类型 | 描述 |
---|---|---|
type | 字符串 | 模块的类型 |
description | 字符串 | 模块的描述 |
version | 向量 [a, b, c] | 模块的版本 |
uuid | 字符串 | 模块的标识 |
我们需要分别为 \BP\manifest.json
和 \RP\manifest.json
添加行为包模块(data
)与资源包模块(resources
)
dependencies
dependencies所需要包含的内容:
名称 | 数据类型 | 描述 |
---|---|---|
uuid | 字符串 | 所依赖的附加包的 uuid |
version | 向量 [a, b, c] | 所依赖的附加包的版本 |
为了将行为包与资源包关联起来,我们需要将他们添加到对方的 dependencies
中
现在,我们的清单文件应该是这样的:
\BP\manifest.json
:
{
"format_version":2,
"header":{
"name":"Ore Crops (BP)",
"description":"Ore Crops behavior pack",
"uuid":"c5960d44-cfa8-457d-83e4-ccc56fbc22e4",
"version":[0,0,1],
"min_engine_version":[1,18,10]
},
"modules":[
{
"type":"data",
"description":"Ore Crops behavior pack",
"uuid":"713b3a86-1a48-c1b2-26f8-4416db5b876b",
"version":[0,0,1]
}
],
"dependencies":[
{
"uuid":"330199b2-ea33-da59-8cb9-c412055d23e9",
"version":[0,0,1]
}
]
}
\RP\manifest.json
:
{
"format_version":2,
"header":{
"name":"Ore Crops (RP)",
"description":"Ore Crops resource pack",
"uuid":"330199b2-ea33-da59-8cb9-c412055d23e9",
"version":[0,0,1],
"min_engine_version":[1,18,10]
},
"modules":[
{
"type":"resources",
"description":"Ore Crops resource pack",
"uuid":"0e262f01-38dc-b893-0902-cb0140885a43",
"version":[0,0,1]
}
],
"dependencies":[
{
"uuid":"c5960d44-cfa8-457d-83e4-ccc56fbc22e4",
"version":[0,0,1]
}
]
}
图标文件 pack_icon.png
别忘了设置一个图标!
在 \BP
和 \RP
目录下放置 pack_icon.png
即可
完成了这些,我们可以正式开始开发工作了 ——
第一个物品
添加物品
首先你需要在 \BP\items
目录下创建一个 .json
文件,文件名随意,这里使用 coal_seed.json
作为“煤炭种子”的物品 json 文件。
物品 json 文件的基本格式如下
{
"format_version":"1.18.0", // 游戏版本号
"minecraft:item":{
"description":{
// 物品的基本信息
},
"components":{
// 物品的组件
},
"events":{
// 物品的事件
}
}
}
description
的基本结构如下:
名称 | 数据类型 | 描述 |
---|---|---|
identifier | 字符串 | 物品的命名空间与物品名构成的标识 |
category | 字符串 | 物品在创造模式物品栏的分类 |
is_experimental | 布尔值 | 物品是否为实验性物品 |
首先是 identifier
,命名空间一般为 addon 的名称,这里“煤炭种子”可以设置为 orecrops:coal_seed
category
的可选值有:equipment
(装备), items
(物品), natural
(自然), block
(建筑), commands
(不可通过命令获取)。这里我们选择 natural
is_experimental
将决定物品是否需开启实验性玩法才可获得,默认值为 false
现在,你的 \BP\items\coal_seed.json
应该是这样子的:
{
"format_version":"1.18.0",
"minecraft:item":{
"description":{
"identifier":"orecrops:coal_seed",
"category":"natural"
}
}
}
至此,你已经成功添加了你的第一个物品!
但是它还缺少纹理、名字等等一些必要属性,下面我们为它定义一个纹理
定义纹理与物品名称
定义纹理
转到 \RP\textures\items
目录,在这里放置你的物品纹理
回到 \RP\textures
目录,在这里新建一个名为 item_texture.json
的文件,在里面输入下面的内容来定义物品纹理
{
"resource_pack_name":"Ore Crops resource pack",
"texture_name":"atlas.items",
"texture_data":{
"coal_seed":{
"textures":"textures/items/fang/coal_seed"
}
}
}
名称 | 描述 |
---|---|
resource_pack_name | 资源包的名称,可填vanilla或其他名称[存疑] |
texture_name | 请填为 atlas.item [存疑] |
texture_data | 纹理资源 "纹理名称":{"textures":"纹理路径"} |
物品名称
我们在 \RP\texts
目录下新建一个 zh_CN.lang
, 在里面输入:
item.orecrops:coal_seed.name=煤炭种子
我们在 zh_CN.lang
中输入的这一行定义了在简体中文语言下 item.orecrops:coal_seed.name
键所对应的文本,以这种方式设置物品名称将方便我们后续进行本地化,与本地化相关的内容我们会在最后学习
到这里你可能会很疑惑,为什么我的物品还是没有纹理?
我们成功添加了一个物品并定义了他的纹理,下面我们将使用组件赋予它名字、纹理与一些作为物品该有的基本属性
物品组件
我们将使用到下表中的组件,更多组件请查阅文档
组件名称 | 描述 |
---|---|
minecraft:creative_category | 注册物品到创造模式物品栏的指定分类、分组 |
minecraft:display_name | 设置物品显示的名称(可使用本地化键名) |
minecraft:icon | 设置物品显示的纹理 |
minecraft:max_stack_size | 设置物品的最大堆叠数量 |
minecraft:creative_category
"minecraft:creative_category": {
"parent": "分组"
}
下面是一些分组
字符串 | 组名 |
---|---|
itemGroup.name.anvil | 铁砧 |
itemGroup.name.arrow | 箭 |
itemGroup.name.axe | 斧 |
itemGroup.name.banner | 旗帜 |
itemGroup.name.banner_pattern | 旗帜图案 |
itemGroup.name.bed | 床 |
itemGroup.name.boat | 船 |
itemGroup.name.boots | 靴子 |
itemGroup.name.buttons | 按钮 |
itemGroup.name.candles | 蜡烛 |
itemGroup.name.chest | 箱子 |
itemGroup.name.chestBoat | 运输船 |
itemGroup.name.chestplate | 胸甲 |
itemGroup.name.concrete | 混凝土 |
itemGroup.name.concretePowder | 混凝土粉末 |
itemGroup.name.cookedFood | 熟食 |
itemGroup.name.copper | 铜 |
itemGroup.name.copperHorn | Copper Horn |
itemGroup.name.coral | 珊瑚块 |
itemGroup.name.coral_decorations | 珊瑚装饰 |
itemGroup.name.crop | 农作物 |
itemGroup.name.door | 门 |
itemGroup.name.dye | 染料 |
itemGroup.name.element | 元素 |
itemGroup.name.enchantedBook | 附魔书 |
itemGroup.name.fence | 栅栏 |
itemGroup.name.fenceGate | 栅栏门 |
itemGroup.name.firework | 烟花火箭 |
itemGroup.name.fireworkStars | 烟火之星 |
itemGroup.name.flower | 花 |
itemGroup.name.glass | 玻璃 |
itemGroup.name.glassPane | 玻璃板 |
itemGroup.name.glazedTerracotta | 带釉陶瓦 |
itemGroup.name.goatHorn | 山羊角 |
itemGroup.name.grass | 地被植物 |
itemGroup.name.helmet | 头盔 |
itemGroup.name.hoe | 锄 |
itemGroup.name.horseArmor | 马凯 |
itemGroup.name.leaves | 树叶 |
itemGroup.name.leggings | 护腿 |
itemGroup.name.lingeringPotion | 滞留药水 |
itemGroup.name.log | 原木 |
itemGroup.name.minecart | 矿车 |
itemGroup.name.miscFood | 其他食物 |
itemGroup.name.mobEgg | 刷怪蛋 |
itemGroup.name.monsterStoneEgg | 被虫蚀的石头 |
itemGroup.name.mushroom | 蘑菇 |
itemGroup.name.netherWartBlock | 下界疣块 |
itemGroup.name.ore | 矿石 |
itemGroup.name.pickaxe | 镐 |
itemGroup.name.planks | 木板 |
itemGroup.name.potion | 药水 |
itemGroup.name.pressurePlate | 压力板 |
itemGroup.name.rail | 铁轨 |
itemGroup.name.rawFood | 生食 |
itemGroup.name.record | 唱片 |
itemGroup.name.sandstone | 砂岩 |
itemGroup.name.sapling | 树苗 |
itemGroup.name.seed | 种子 |
itemGroup.name.shovel | 锹 |
itemGroup.name.shulkerBox | 潜影盒 |
itemGroup.name.sign | 告示牌 |
itemGroup.name.skull | 头颅 |
itemGroup.name.slab | 台阶 |
itemGroup.name.splashPotion | 喷溅药水 |
itemGroup.name.stainedClay | 陶瓦 |
itemGroup.name.sculk | Sculk |
itemGroup.name.stairs | 楼梯 |
itemGroup.name.stone | 石头 |
itemGroup.name.stoneBrick | 石砖 |
itemGroup.name.sword | 剑 |
itemGroup.name.trapdoor | 活板门 |
itemGroup.name.walls | 墙 |
itemGroup.name.wood | 木头 |
itemGroup.name.wool | 羊毛 |
itemGroup.name.woolCarpet | 地毯 |
我们使用这个组件将“煤炭种子”归入“种子”分组
minecraft:display_name
"minecraft:display_name": {
"name":"名称或本地化键名"
}
在上一节我们定义了“煤炭种子”的本地化键名(item.orecrops:coal_seed.name
),直接填进去即可
minecraft:icon
"minecraft:icon": {
"texture":"纹理名称"
}
在上一节我们定义了“煤炭种子”的纹理名称(coal_seed
),直接填进去即可
minecraft:max_stack_size
"minecraft:max_stack_size": 堆叠上限
堆叠上限是一个大于等于 1
小于等于 64
的整数型值
我们设置为 64
现在,我们的 coal_seed.json
应该是这样的:
{
"format_version":"1.18.0",
"minecraft:item":{
"description":{
"identifier":"orecrops:coal_seed",
"category":"nature"
},
"components":{
"minecraft:display_name":{
"value":"item.orecrops:coal_seed.name"
},
"minecraft:creative_category":{
"parent":"itemGroup.name.seed"
},
"minecraft:max_stack_size":64,
"minecraft:icon":{
"texture":"coal_seed"
}
}
}
}
现在,你的第一个物品已经有了名字、纹理,下面我们来完成你的第一个方块
第一个方块
添加方块
在 \BP\blocks
目录创建一个名为 coal_crops.json
的文件作为“煤炭作物”的作物方块
方块 json 文件的基本格式如下
{
"format_version": "1.18.0", // 游戏版本
"minecraft:block": {
"description": {
// 描述
},
"components": {
// 组件
},
"events": {
// 事件
},
"permutations": [
//置换
]
}
}
方块的描述部分与物品稍有不同:
名称 | 数据类型 | 描述 |
---|---|---|
identifier | 字符串 | 方块的命名空间与物品名构成的标识 |
properties | 对象 | 方块的属性 |
is_experimental | 布尔值 | 方块是否为实验性方块 |
identifier
我们设置为 orecrops:coal_crop
properties
在下一章将具体学习
is_experimental
与物品相同,默认值为 false
现在,你的 \BP\blocks\coal_crop.json
应该是这样的:
{
"format_version":"1.18.0",
"minecraft:block":{
"description":{
"identifier":"orecrops:coal_crop"
}
}
}
定义纹理
将作物的不同生长状态的纹理放进 \RP\textures\blocks
中,本教程中我为作物设置了 8 个不同生长阶段
回到 \RP\textures
目录,新建 terrain_texture.json
,在里面输入:
{
"resource_pack_name":"Ore Crops resource pack",
"texture_name":"atlas.terrain",
"num_mip_levels":4,
"padding":8,
"texture_data":{
"coal_crop_0":{
"textures":"textures/blocks/fang/crop_stage_0"
},
"coal_crop_1":{
"textures":"textures/blocks/fang/crop_stage_1"
},
"coal_crop_2":{
"textures":"textures/blocks/fang/crop_stage_2"
},
"coal_crop_3":{
"textures":"textures/blocks/fang/crop_stage_3"
},
"coal_crop_4":{
"textures":"textures/blocks/fang/crop_stage_4"
},
"coal_crop_5":{
"textures":"textures/blocks/fang/coal_stage_5"
},
"coal_crop_6":{
"textures":"textures/blocks/fang/coal_stage_6"
},
"coal_crop_7":{
"textures":"textures/blocks/fang/coal_stage_7"
}
}
}
我们还需要在资源包中为方块指定纹理,回到 \RP
目录
创建 blocks.json
,为我们的作物方块指定纹理和音效
{
"format_version":"1.18.0",
"orecrops:coal_crop":{
"textures":"coal_crop_0",
"sound":"grass"
}
}
textures
的值也可以是一个对象,用来设置方块不同面的纹理,例如这样:
"textures":{
"down" : "log_end",
"side" : "log_side",
"up" : "log_end"
}
现在它是一个有纹理的方块了,但是看起来一点都不像一个作物该有的样子,我们需要为它制作一个模型
打开 Blockbench,为它制作一个模型(更多 Blockbench 的用法,请查阅此教程)
选择新建 Bedrock Model
设置好后点击 Confirm
制作出想要的模型(新建两个 cube,将 Size 的第三个值设置成 0 就成薄片状了)
将导出的模型放在 \RP\models\entity
中,之后我们就可以通过组件为方块设置模型和必要属性了
方块组件
我们将使用到下表中的组件,更多组件请查阅文档
名称 | 描述 |
---|---|
minecraft:collision_box | 设置方块的碰撞箱 |
minecraft:geometry | 设置方块的模型 |
minecraft:placement_filter | 设置方块被放置时的条件 |
minecraft:collision_box
// 对象写法
"minecraft:collision_box":{
"origin": 锚点,
"size": 尺寸
}
// 布尔值写法
"minecraft:collision_box": 布尔值
以上是 minecraft:collision_box
组件的不同写法,当布尔值写法的数据值设置为 false
时则禁用碰撞箱,也就是说下面两种写法是等价的
// 对象写法
"minecraft:collision_box":{
"origin": [0, 0, 0],
"size": [0, 0, 0]
}
// 布尔值写法
"minecraft:collision_box": false
在原版中的作物方块实体是可以自由穿过的,这里我们可以直接将 minecraft:collision_box
的数据值设置为 false
禁用碰撞箱
minecraft:geometry
"minecraft:geometry": "几何模型"
还记得你在上一节设置的 Model Identifier 吗?将它填进去就好
minecraft:placement_filter
"minecraft:placement_filter": {
"conditions": [ // 条件可以设置多个
{
"block_filter": 方块数组,
"allowed_faces": 面数组
}
]
}
我们的作物方块只可以放置在耕地方块的上面,block_filter
设置为 ["farmland"]
,allowed_faces
设置为 ["up"]
另:allowed_faces
可选的值有 up
(顶面)、down
(底面)、north
(北面)、south
(南面)、east
(东面)、west
(西面)、side
(侧面)、all
(所有面)
现在我们的 coal_crops.json
应该是这样的:
{
"format_version":"1.18.0",
"minecraft:block":{
"description":{
"identifier":"orecrops:coal_crop"
},
"components":{
"minecraft:collision_box":false,
"minecraft:geometry":"geometry.crop",
"minecraft:placement_filter":{
"conditions":[
{
"block_filter":["farmland"],
"allowed_faces":["up"]
}
]
}
}
}
}
种子、作物
种子
我们将使用 minecraft:block_placer
组件让“煤炭种子”拥有放置方块的能力,在放置方块的同时将使用一个物品
"minecraft:block_placer":{
"block": "方块的标识",
"use_on": 可以在何种方块上使用(数组)
}
写好后应该长这样:
"minecraft:block_placer":{
"block": "orecrops:coal_crop",
"use_on": ["farmland"]
}
大功告成!物品这一部分我们已经彻底完成了 ——
{
"format_version":"1.18.0",
"minecraft:item":{
"description":{
"identifier":"orecrops:coal_seed",
"category":"nature"
},
"components":{
"minecraft:display_name":{
"value":"item.orecrops:coal_seed.name"
},
"minecraft:creative_category":{
"parent":"itemGroup.name.seed"
},
"minecraft:max_stack_size":64,
"minecraft:icon":{
"texture":"coal_seed"
},
"minecraft:block_placer":{
"block":"orecrops:coal_crop",
"use_on":["farmland"]
}
}
}
}
作物
不同生长状态
为了实现不同生长状态,我们首先需要在方块的描述中为方块定义一个属性(properties),它们类似“变量”,一个方块可以拥有多个属性,属性的值可以是数字、布尔值或字符串
我们先为作物方块定义一个 orecrops:growth
属性,来储存它的不同生长阶段
"properties":{
"orecrops:growth":[0, 1, 2, 3, 4, 5, 6, 7]
}
为了让作物方块在不同生长阶段拥有不同的纹理,我们需要使用置换(permutations)
在置换部分我们要接触到 Molang 了!
下面是 permutations 的格式,你可以设置不同条件对应不同欲被替换的组件
{
"condition":"条件",
"components": 欲被替换的组件
}
条件部分我们可以使用 Molang,在这里我们通常使用 Molang 的逻辑运算符对值进行判断
运算符 | 描述 | 示例 | |
---|---|---|---|
! | 逻辑非运算符。使一个表达式的结果从 true 变为 false ,从 false 变为 true。 | !query.can_fly | |
&& | 逻辑与运算符。只有当两个表达式都为true 时,整个表达式的结果才为true。 | query.can_walk == 1 && query.can_climb == 1 | |
\ | 逻辑或运算符。只要其中任意一个表达式为 true 整个表达式都为 true。 | `query.can_walk == 1 | |
< | 小于运算符。比较左右两边表达式数值的大小,若左边小于右边即为 true,反之则为 false。 | query.total_particle_count < 5 | |
<= | 小于等于运算符。用于比较左右两边表达式数值的大小,若左边小于或等于右边即为 true,反之则为 false。 | query.trade_tier <= 2 | |
>= | 大于等于运算符。用于比较左右两边表达式数值的大小,若左边大于或等于右边即为 true,反之则为 false。 | query.health >= 5 | |
> | 大于运算符。用于比较左右两边表达式数值的大小,若左边大于右边即为 true,反之则为 false。 | query.day > 7 | |
== | 等于运算符。若左边与右边表达式的结果相等时即为 true,反之则为 false。 | query.block_face == query.cardinal_player_facing | |
!= | 不等于运算符。若左边与右边表达式的结果不相等时即为 true,反之则为 false。 | query.body_x_rotation != query.body_y_rotation |
我们需要判断此前设置的 orecrops:growth 的值是否为特定值,所以选用等于运算符 ==
若要获取 orecrops:growth 还需要用到查询函数 query.block_property()
,这个函数需要传入一个参数,参数则是要查询的属性名称
我们的煤炭作物生长第一阶段的“条件”是:query.block_property('orecrops:growth') == 0
我们共需要设置 8 个这样的置换,来做到 8 个生长状态:
"permutations": [
{
"condition":"query.block_property('orecrops:growth') == 0",
"components":{
"minecraft:material_instances":{
"*":{
"texture":"crop_0",
"render_method":"alpha_test"
}
}
}
},
{
"condition":"query.block_property('orecrops:growth') == 1",
"components":{
"minecraft:material_instances":{
"*":{
"texture":"coal_crop_1",
"render_method":"alpha_test"
}
}
}
},
{
"condition":"query.block_property('orecrops:growth') == 2",
"components":{
"minecraft:material_instances":{
"*":{
"texture":"coal_crop_2",
"render_method":"alpha_test"
}
}
}
},
{
"condition":"query.block_property('orecrops:growth') == 3",
"components":{
"minecraft:material_instances":{
"*":{
"texture":"coal_crop_3",
"render_method":"alpha_test"
}
}
}
},
{
"condition":"query.block_property('orecrops:growth') == 4",
"components":{
"minecraft:material_instances":{
"*":{
"texture":"coal_crop_4",
"render_method":"alpha_test"
}
}
}
},
{
"condition":"query.block_property('orecrops:growth') == 5",
"components":{
"minecraft:material_instances":{
"*":{
"texture":"coal_crop_5",
"render_method":"alpha_test"
}
}
}
},
{
"condition":"query.block_property('orecrops:growth') == 6",
"components":{
"minecraft:material_instances":{
"*":{
"texture":"coal_crop_6",
"render_method":"alpha_test"
}
}
}
},
{
"condition":"query.block_property('orecrops:growth') == 7",
"components":{
"minecraft:material_instances":{
"*":{
"texture":"coal_crop_7",
"render_method":"alpha_test"
}
}
}
}
]
生长
我们在上一节已经完整了作物的不同生长阶段,下面我们使用触发器组件与自定义事件完成作物的自然生长与骨粉催熟
我们先来设置事件,先来一个生长事件:
"grow_event":{ // 自定义事件名
"randomize":[ // 随机执行一个事件组
{
"weight":1 // 权重,如果随机到这里什么都不会发生
},
{
"weight":1, // 权重
"set_block_property":{ // 设置方块的属性的值
"orecrops:growth":"(query.block_property('orecrops:growth')<7) ? query.block_property('orecrops:growth') + 1 : 7" // 在下方详细解释
}
}
]
}
set_block_property
中我们使用了 Molang 让 orecrops:growth
增加
这里我们用到了 Molang 的三元条件运算符 ?:
:当问号左边的表达式为真,则将问号与冒号中间表达式的值作为整个表达式的取值,反之则将冒号后面表达式的值作为整个表达式的取值。
翻译成人话就是:若 orecrops:growth
小于 7
让 orecrops:growth + 1
,否则设置 orecrops:growth
为 7
下面我们来完成骨粉催熟事件
"usebonemeal_event": { // 自定义事件名
"sequence":[ // 执行下面的所有事件
{
"decrement_stack":{ // 减少一个手持的物品
"ignore_game_mode":false // 是否忽略游戏模式
}
},
{
"run_command":{ // 执行命令
"command":[ // 命令(数组)
"particle minecraft:crop_growth_emitter ~ ~ ~" // 在方块处生成 crop_growth_emitter 粒子
]
}
},
{
"trigger":{
"event":"grow_event" // 执行自定义事件“grow_event”
}
}
]
}
完成事件后我们还需要使用触发器组件来触发这些事件
"minecraft:on_interact": { // 右键触发器组件
"condition":"query.get_equipped_item_name('main_hand') == 'bone_meal'", // 触发条件是拿着骨粉右键
"event":"usebonemeal_event" // 触发拿着骨粉右键将触发 usebonemeal_event 事件
},
"minecraft:random_ticking": { // 随机刻组件
"on_tick":{ // 触发器
"event":"grow_event" // 触发 grow_event 事件
}
}
现在我们的 coal_crop.json
是这个样子的:
{
"format_version":"1.18.0",
"minecraft:block":{
"description":{
"identifier":"orecrops:coal_crop",
"properties":{
"orecrops:growth":[0, 1, 2, 3, 4, 5, 6, 7]
}
},
"components":{
"minecraft:geometry":"geometry.crop",
"minecraft:collision_box":false,
"minecraft:placement_filter":{
"conditions":[
{
"block_filter":["farmland"],
"allowed_faces":["up"]
}
]
},
"minecraft:on_interact":{
"condition":"query.get_equipped_item_name('main_hand') == 'bone_meal'",
"event":"usebonemeal_event"
},
"minecraft:random_ticking":{
"on_tick":{
"event":"grow_event"
}
}
},
"events":{
"grow_event":{
"randomize":[
{
"weight":1
},
{
"weight":1,
"set_block_property":{
"orecrops:growth":"(query.block_property('orecrops:growth')<7) ? query.block_property('orecrops:growth') + 1 : 7"
}
}
]
},
"usebonemeal_event":{
"sequence":[
{
"decrement_stack":{
"ignore_game_mode":false
}
},
{
"run_command":{
"command":[
"particle minecraft:crop_growth_emitter ~ ~ ~"
]
}
},
{
"trigger":{
"event":"grow_event"
}
}
]
}
},
"permutations":[
{
"condition":"query.block_property('orecrops:growth') == 0",
"components":{
"minecraft:material_instances":{
"*":{
"texture":"coal_crop_0",
"render_method":"alpha_test"
}
}
}
},
{
"condition":"query.block_property('orecrops:growth') == 1",
"components":{
"minecraft:material_instances":{
"*":{
"texture":"coal_crop_1",
"render_method":"alpha_test"
}
}
}
},
{
"condition":"query.block_property('orecrops:growth') == 2",
"components":{
"minecraft:material_instances":{
"*":{
"texture":"coal_crop_2",
"render_method":"alpha_test"
}
}
}
},
{
"condition":"query.block_property('orecrops:growth') == 3",
"components":{
"minecraft:material_instances":{
"*":{
"texture":"coal_crop_3",
"render_method":"alpha_test"
}
}
}
},
{
"condition":"query.block_property('orecrops:growth') == 4",
"components":{
"minecraft:material_instances":{
"*":{
"texture":"coal_crop_4",
"render_method":"alpha_test"
}
}
}
},
{
"condition":"query.block_property('orecrops:growth') == 5",
"components":{
"minecraft:material_instances":{
"*":{
"texture":"coal_crop_5",
"render_method":"alpha_test"
}
}
}
},
{
"condition":"query.block_property('orecrops:growth') == 6",
"components":{
"minecraft:material_instances":{
"*":{
"texture":"coal_crop_6",
"render_method":"alpha_test"
}
}
}
},
{
"condition":"query.block_property('orecrops:growth') == 7",
"components":{
"minecraft:material_instances":{
"*":{
"texture":"coal_crop_7",
"render_method":"alpha_test"
}
}
}
}
]
}
}
现在,一个可生长的作物已经初步成型了,等等——破坏掉它没有掉落物?!
收获
战利品表
我们需要使用战利品表自定义作物的掉落物
在 \BP\loot_tables
目录新建 coal_seed.json
文件作为物品还未成熟时的掉落物的战利品表
{
"pools":[ // 随机池列表
{
"rolls":1, // 此随机池中的抽取次数
"entries":[
{
"weight":1, // 权重
"type":"item", // 战利品的类型
"name":"orecrops:coal_seed", // 战利品的标识
"functions":[ // 函数列表
{
"function":"set_count", // 函数名(设置战利品的数量)
"count":1 // 数量为 1
}
]
}
]
}
]
}
在 \BP\loot_tables
目录新建 coal_crop.json
文件作为物品已经成熟时的掉落物的战利品表
{
"pools":[
{
"rolls":1,
"entries":[
{
"weight":1,
"type":"item",
"name":"orecrops:coal_seed",
"functions":[
{
"function":"set_count",
"count":{
"min":0, // 随机 0~2 个战利品
"max":2
}
}
]
}
]
},
{
"rolls":1,
"entries":[
{
"weight":1,
"type":"item",
"name":"minecraft:coal",
"functions":[
{
"function":"set_count",
"count":{
"min":1, // 随机 1~3 个战利品
"max":3
}
}
]
}
]
}
]
}
回到方块的 json 文件,使用 minecraft:loot
组件设置战利品表
我们为未成熟的作物方块设置 coal_seed.json
战利品
为成熟的作物方块设置 coal_crop.json
战利品
收获事件
为了在作物成熟的时候右键即可收获,且一株作物可以多次结果矿物,我们可以新增一个自定义事件 harvest_event
"harvest_event":{
"spawn_loot":{ // 生成战利品表
"table":"loot_tables/coal_crop.json"
},
"set_block_property":{ // 设置 orecrops:growth 为 5
"orecrops:growth":"5"
}
}
我们还需要在 orecrops:growth
为 7
时的置换中置换 minecraft:on_interact
事件和 minecraft:loot
事件
{
"condition":"query.block_property('orecrops:growth') == 7",
"components":{
"minecraft:material_instances":{
"*":{
"texture":"coal_crop_7",
"render_method":"alpha_test"
}
},
"minecraft:loot":"loot_tables/coal_crop.json",
"minecraft:on_interact":{
"event":"harvest_event"
}
}
}
最终,我们的 coal_crop.json
是这样的:
{
"format_version":"1.18.0",
"minecraft:block":{
"description":{
"identifier":"orecrops:coal_crop",
"properties":{
"orecrops:growth":[0, 1, 2, 3, 4, 5, 6, 7]
}
},
"components":{
"minecraft:loot":"loot_tables/coal_seed.json",
"minecraft:geometry":"geometry.crop",
"minecraft:collision_box":false,
"minecraft:placement_filter":{
"conditions":[
{
"block_filter":["farmland"],
"allowed_faces":["up"]
}
]
},
"minecraft:on_interact":{
"condition":"query.get_equipped_item_name('main_hand') == 'bone_meal'",
"event":"usebonemeal_event"
},
"minecraft:random_ticking":{
"on_tick":{
"event":"grow_event"
}
}
},
"events":{
"grow_event":{
"randomize":[
{
"weight":1
},
{
"weight":1,
"set_block_property":{
"orecrops:growth":"(query.block_property('orecrops:growth')<7) ? query.block_property('orecrops:growth') + 1 : 7"
}
}
]
},
"harvest_event":{
"spawn_loot":{
"table":"loot_tables/coal_crop.json"
},
"set_block_property":{
"orecrops:growth":"5"
}
},
"usebonemeal_event":{
"sequence":[
{
"decrement_stack":{
"ignore_game_mode":false
}
},
{
"run_command":{
"command":[
"particle minecraft:crop_growth_emitter ~ ~ ~"
]
}
},
{
"trigger":{
"event":"grow_event"
}
}
]
}
},
"permutations":[
{
"condition":"query.block_property('orecrops:growth') == 0",
"components":{
"minecraft:material_instances":{
"*":{
"texture":"coal_crop_0",
"render_method":"alpha_test"
}
},
"minecraft:loot":"loot_tables/coal_seed.json"
}
},
{
"condition":"query.block_property('orecrops:growth') == 1",
"components":{
"minecraft:material_instances":{
"*":{
"texture":"coal_crop_1",
"render_method":"alpha_test"
}
},
"minecraft:loot":"loot_tables/coal_seed.json"
}
},
{
"condition":"query.block_property('orecrops:growth') == 2",
"components":{
"minecraft:material_instances":{
"*":{
"texture":"coal_crop_2",
"render_method":"alpha_test"
}
},
"minecraft:loot":"loot_tables/coal_seed.json"
}
},
{
"condition":"query.block_property('orecrops:growth') == 3",
"components":{
"minecraft:material_instances":{
"*":{
"texture":"coal_crop_3",
"render_method":"alpha_test"
}
},
"minecraft:loot":"loot_tables/coal_seed.json"
}
},
{
"condition":"query.block_property('orecrops:growth') == 4",
"components":{
"minecraft:material_instances":{
"*":{
"texture":"coal_crop_4",
"render_method":"alpha_test"
}
},
"minecraft:loot":"loot_tables/coal_seed.json"
}
},
{
"condition":"query.block_property('orecrops:growth') == 5",
"components":{
"minecraft:material_instances":{
"*":{
"texture":"coal_crop_5",
"render_method":"alpha_test"
}
},
"minecraft:loot":"loot_tables/coal_seed.json"
}
},
{
"condition":"query.block_property('orecrops:growth') == 6",
"components":{
"minecraft:material_instances":{
"*":{
"texture":"coal_crop_6",
"render_method":"alpha_test"
}
},
"minecraft:loot":"loot_tables/coal_seed.json"
}
},
{
"condition":"query.block_property('orecrops:growth') == 7",
"components":{
"minecraft:material_instances":{
"*":{
"texture":"coal_crop_7",
"render_method":"alpha_test"
}
},
"minecraft:loot":"loot_tables/coal_crop.json",
"minecraft:on_interact":{
"event":"harvest_event"
}
}
}
]
}
}
至此,种子与作物方块已经全部完成了,下面一章我们将学习使用自定义合成配方
合成种子
有序合成配方的基本结构
{
"format_version":"1.12",
"minecraft:recipe_shaped":{
"description":{
// 描述
},
"tags":[
// 类别
],
"pattern":[
// 样式
],
"key":{
// 材料
},
"result":{
// 成品
}
}
}
pattern
:有序合成的物品摆放样式
key
:使用字符代表物品,用在 pattern
中
// 写法1
"字符":"物品的标识"
//写法2
"字符":{
"item": "物品的标识",
"data": "物品的特殊值(支持 Molang)"
}
在 \BP\recipes
目录新建一个 coal_seed.json
看看下面 coal_seed.json
的例子就懂了 ——
{
"format_version":"1.18.0",
"minecraft:recipe_shaped": {
"description":{
"identifier": "orecrops:coal_seed"
},
"tags": ["crafting_table"],
"pattern": [
"OOO",
"OSO",
"OOO"
],
"key": {
"O": {
"item": "minecraft:coal"
},
"S": {
"item": "minecraft:wheat_seeds"
}
},
"result":{
"item": "orecrops:coal_seed"
}
}
}
向世界推广你的 Addon
为了适配不同语言的游戏,我们在很早就做好了本地化的准备。现在,如果你想增加一门语言的支持,只需要在 \RP\texts
目录新建一个 语言代号.lang
,例如 en_US.lang
在这些语言文件中增加两行:
pack.description=资源包的描述
pack.name=矿石作物
修改你的包名和描述为 pack.name
和 pack.description
再新建一个文件 languages.json
,输入:
[
"zh_CN",
"en_US"
]
这样就可以做到预读取语言文件,在不同语言下附加包的名称与描述都会变为与对应语言文件中对应的文本
完
参考与引用
本文在撰写过程中参考或引用了来自以下网站的文本
- Minecraft: Bedrock Edition Creator Documentation | Microsoft Docs
- Bedrock Wiki
- bedrock.dev
- 中文Minecraft Wiki
致谢
感谢以下组织、个人、网站和软件在教程编写过程中对本人提供的帮助
- 感谢 RarityEG's Plugin Dev Tutorial 给予本人教程编写模式的灵感
- 感谢 MarkText 的开发者制作了这么棒的 Markdown 编辑器
- 感谢 ustc-zzzz (Yanbing Zhao) 开发的 MCBBS Markdown To BBCode Converter 提供 Markdown 转 BBCode 服务
- 感谢阅读至此的你
在“开始的开始”部分中清单文件的部分,有误,出现两个BP,第二个应为RP
感谢反馈,已经改正 www