This commit is contained in:
boybook
2025-12-01 20:59:16 +08:00
parent 12738a142c
commit 760c2dd9ad
5535 changed files with 21070 additions and 2021 deletions

View File

@@ -0,0 +1,15 @@
---
front: https://nie.res.netease.com/r/pic/20211104/69055361-2e7a-452f-8b1a-f23e1262a03a.jpg
hard: 入门
time: 5分钟
---
# 摘要
在学习完自定义物品之后,我们来学习如何自定义方块。
- 在第一节(*认识自定义方块*)中,我们将学习自定义方块的基本格式。
- 在第二节(*制作一个苹果方块*我们将一起用Blockbench制作一个方块模型并将其挂接在方块中。
- 在最后一节(*挑战:制作一个发光地灯*)中,我们将一起进行一个发光地灯的挑战方块制作。
本章关键词:方块 格式版本 描述 组件 图集 方块模型 苹果 地灯

View File

@@ -0,0 +1,177 @@
---
front: https://nie.res.netease.com/r/pic/20211104/69055361-2e7a-452f-8b1a-f23e1262a03a.jpg
hard: 高级
time: 15分钟
---
# 认识自定义方块
在本节中,我们一起考察自定义方块的格式。依据惯例,我们先使用编辑器快速创建一个自定义方块,以便于我们查看它的基本结构。
![](./images/10.1_block_config.png)
我们选择“方块配置”,然后创建一个空的自定义方块。
![](./images/10.1_block_create.png)
我们可以看到,编辑器提示我们将创建以下配套文件:
```shell
./behavior_pack/netease_blocks/tutorial_demo_block_demo.json
```
![](./images/10.1_block_created.png)
从文件的结构可以看到,我们的自定义方块只有一个行为包定义文件。但是事实上,方块也是需要客户端定义的,不过这个客户端定义比较特殊,不像物品和实体那样是单独的一个文件。方块的客户端定义文件是一个单独的文件,其中包含了所有需要定义的方块的客户端资源,那便是资源包根目录下的`blocks.json`
不过,在此之前,我们先一起来看行为包定义文件。
## 行为包定义
```json
{
"format_version": "1.10.0",
"minecraft:block": {
"description": {
"identifier": "tutorial_demo:block_demo",
"category": "construction",
"base_block": "none"
},
"components": {
}
}
}
```
- `format_version`:这是这个方块的**格式版本****Format Version**)。方块稳定的格式版本有`1.10.0``1.16.0`,它们均不需要开启实验性玩法,我们依旧推荐格式版本`1.10.0``1.16.100`及以上的格式版本意味着新版方块,这需要开启实验性玩法,我们不推荐使用。同样,如果使用`1.16.100`及以上的新版方块,则只需创建行为包定义文件,客户端需要的数据将从服务端通过来自数据包的形式接收。
- `minecraft:block`:方块的模式标识符。其下有`description``components`对象。
我们再依次查看`description`对象下的属性。
- `identifier`:字符串,该方块的赋命名空间标识符,格式为`<namespace>:<identifier>`。需要注意的是,由于方块的内部代码限制,就算我们设定了命名空间,但是依旧无法避免重名冲突现象。这是因为方块作为方块物品存在时可以使用带有命名空间的标识符作为唯一标识符,但是方块作为自身或世界中的实例时只能够使用上述格式中的`<identifier>`作为标识符。所以我们依旧要保证上述格式中的`<identifier>`的唯一性,比如,我们可以使用类似`<namespace>:<namespace>_<name>`的格式来保证其唯一性。
- `category`:可选,字符串,将物品注册到创造物品栏的分类。默认为`construction`(建筑)。若填写`commands`则只能通过指令和api获取填写`none`则只能通过api获取支持填入自定义分页的名称。
- `base_block`:可选,字符串,中国版特有的描述属性,可以继承原版的一些种类的方块,从而定义具有原版硬编码特性的方块。目前可以填写`mob_spawner``portal``custom_crop_block``liquid``custom_heavy_block`等。
## 资源包定义
资源包定义文件在资源包根目录下的`blocks.json`,所有的方块的资源包定义皆集中在这一个方块中。
```json
{
"format_version": [ 1, 1, 0 ],
"tutorial_demo:block_demo": {
"textures": "tutorial_demo:dirt"
}
}
```
方块的资源包定义文件的格式版本为非常旧的`1.1.0`,且需要用语义化版本数组的形式写入。下面每一个字段的键名是方块的赋命名空间标识符,值是一个对象,其中`textures`字段是该方块的纹理文件的短名称。方块纹理的短名称和物品的一样,依旧是在一个图集文件中定义的,我们稍后会一起来看方块的图集文件。
我们下面展示一段原版方块的更详细的资源包定义。
```json
{
"format_version": [ 1, 1, 0 ],
"air": {},
"stone": {
"textures": "stone",
"sound": "stone"
},
"grass": {
"isotropic": {
"up": true,
"down": true
},
"textures": {
"up": "grass_top",
"down": "grass_bottom",
"side": "grass_side"
},
"carried_textures": {
"up": "grass_carried_top",
"down": "grass_carried_bottom",
"side": "grass_carried"
},
"sound": "grass"
},
"dirt": {
"isotropic": true,
"textures": "dirt",
"sound": "gravel"
},
// ...
"sand": {
"isotropic": true,
"textures": "sand",
"brightness_gamma": 0.55,
"sound": "sand"
},
// ...
"leaves": {
"isotropic": {
"up": true,
"down": true
},
"textures": "leaves",
"carried_textures": "leaves_carried",
"brightness_gamma": 0.80,
"sound": "grass"
},
// ...
"dispenser": {
"textures": {
"up": "dispenser_top",
"down": "dispenser_top",
"north": "dispenser_side",
"south": "dispenser_front_horizontal",
"west": "dispenser_side",
"east": "dispenser_front_vertical"
},
"carried_textures": {
"up": "dispenser_top",
"down": "dispenser_top",
"north": "dispenser_side",
"south": "dispenser_front_horizontal",
"west": "dispenser_side",
"east": "dispenser_side"
},
"sound": "stone"
},
// ...
}
```
我们可以看到,除了`textures`之外,我们还可以设置声音(`sounds`)、手持纹理(`carried_textures`)、各向异性(`isotropic`)和亮度伽马值(`brightness_gamma`)和等,并且每个面可以单独设置这些值。事实上,我们还可以通过`blockshape`设置方块形状。
声音是用于链接一个系统声音事件(亦称存档声音事件)的集合的。在资源包根目录的`sounds.json`文件的`block_sounds`对象中,我们为每种方块大类设置了一个系统声音事件集,用于方块相关音效的“自动”播放,比如`normal``gravel``wood`等。这里便需要填写对应的系统声音事件集名称。其实实体的音效播放也是如此,只不过实体的系统声音事件集名称和实体标识符是一致的,所以他们可以自动地链接在一起。
各向异性是用于开启纹理的随机旋转的。开启了各向异性的面将采用伪随机的形式通过世界种子进行纹理的随机旋转。
方块形状是一种类似于方块模型的属性。开发者可以用方块形状继承一个原版的方块模型,同时继承所有该模型的渲染方法和渲染属性,比如是否进行背面消隐、环境光遮蔽等。
### 图集
与物品的图集称为物品图集不同,方块的图集称为**地形图集**。
![](./images/10.1_terrain_atlas.png)
我们可以在`textures/terrain_texture.json`处找到方块的图集定义。
```json
{
"resource_pack_name": "tutorial_demo",
"texture_name": "atlas.terrain",
"padding": 8,
"num_mip_levels": 4,
"texture_data": {
"tutorial_demo:dirt": {
"textures": "textures/blocks/dirt"
}
}
}
```
`atlas.terrain`是地形图集的图集标识符,不可以改变为其他的字段。`padding`是每个纹理文件整合为一个大的图集文件时的内边距。我们可以看到上面的示例大图集文件中每个纹理周围都存在一段延伸的边距这便是由该字段定义的这是为了避免MIPMAP过程中不同方块的贴图之间像素融合的问题。`num_mip_levels`是该图集文件进行的MIPMAP次数MIPMAP次数越多远处的方块的噪点越少。在`texture_data`中,便是短名称的定义了。这一点和物品是一致的。
在定义好了我们的方块纹理后,我们的方块便算是初步完成了!

View File

@@ -0,0 +1,210 @@
---
front: https://nie.res.netease.com/r/pic/20211104/69055361-2e7a-452f-8b1a-f23e1262a03a.jpg
hard: 高级
time: 15分钟
---
# 制作一个苹果方块
我们学会了如何自定义一个基本的方块,下面,我们学习如何自定义方块模型。可通过[方块模型资源](https://g79.gdl.netease.com/addonguide-10.zip)将模型资源下载到本地。
## 准备苹果模型
虽然目前最新版的国际版接口已经支持了方块的自定义模型,但是该接口需要`1.16.100`以上的实验性玩法。我们使用中国版单独支持的中国版方块模型。
中国版方块模型也是使用Blockbench支持的模型只不过方块的(0, 0, 0)在模型的(8, 0, 8)处,也就是说整体方块需要以基面中央为西北下角进行制作,并且需要使用“**自由模型**”模式。
![](./images/10.2_apple_bb.png)
我们准备好了一个苹果模型,用来模仿树上挂着的苹果。我们将其保存为`.bbmodel`文件。
## 在编辑器中导入模型
中国版的方块模型使用特殊的文件模式,为了快速将其转换为中国版方块模型格式,我们需要使用编辑器导入模型。我们在“文件管理”窗格中找到导入按钮。
![](./images/10.2_import.png)
我们选择Blockbench模型即可将其导入为方块模型。
![](./images/10.2_importing.png)
输入好模型的标识符,选该模型对应的方块物品贴图文件,点击确定即可成功导入。之后,该文件将被导入至资源包的`models/netease_block`文件夹中。
我们可以来查看该模型文件。可以看到此时这个文件已经被转换成了一个JSON文件。
```json
{
"format_version": "1.13.0",
"netease:block_geometry": {
"description": {
"identifier": "tutorial_demo:apple",
//"item_texture": "tutorial_demo:apple_icon",
"textures": ["tutorial_demo:apple"],
"use_ao": false
},
"bones": [{
"cubes": [{
"origin": [8, 12, 5],
"pivot": [11, 17, 10],
"rotation": [0, 0, 0],
"size": [0, 4, 6],
"uv": {
"down": {
"texture": 0,
"uv": [0, 0],
"uv_size": [0, 3]
},
"east": {
"texture": 0,
"uv": [3, 1],
"uv_size": [3, 2]
},
"north": {
"texture": 0,
"uv": [0, 0],
"uv_size": [0, 3]
},
"south": {
"texture": 0,
"uv": [0, 0],
"uv_size": [0, 3]
},
"up": {
"texture": 0,
"uv": [0, 0],
"uv_size": [0, 3]
},
"west": {
"texture": 0,
"uv": [6, 1],
"uv_size": [-3, 2]
}
}
}, {
"origin": [5, 6, 5],
"pivot": [11, 6, 5],
"rotation": [0, 0, 0],
"size": [6, 6, 6],
"uv": {
"down": {
"texture": 0,
"uv": [6, 3],
"uv_size": [-3, 3]
},
"east": {
"texture": 0,
"uv": [0, 0],
"uv_size": [3, 3]
},
"north": {
"texture": 0,
"uv": [0, 0],
"uv_size": [3, 3]
},
"south": {
"texture": 0,
"uv": [0, 0],
"uv_size": [3, 3]
},
"up": {
"texture": 0,
"uv": [0, 3],
"uv_size": [3, 3]
},
"west": {
"texture": 0,
"uv": [0, 0],
"uv_size": [3, 3]
}
}
}],
"name": "bone",
"pivot": [0, 0, 0],
"rotation": [0, -90, 0]
}]
}
}
```
我们可以看到格式版本为`1.13.0`,模式标识符为`netease:block_geometry`。在`description`中,`identifier`为你刚刚输入的标识符带上了命名空间,`item_texture`为方块物品的纹理贴图的短名称,`textures`是用于本模型UV映射的纹理贴图。`use_ao`为是否为本模型启用**环境光遮蔽****Ambient Occlusion**)。环境光遮蔽是一种描绘物体和物体相交或靠近的时候遮挡周围漫反射光线的效果。
## 使用编辑器配置苹果方块
我们在编辑器中打开方块,找到”**属性**“窗格中的”**基础属性**“,点击”**+**“。
![](./images/10.2_model.png)
我们选择`model`来在方块的描述中添加一个模型字段。
![](./images/10.2_apple_model.png)
我们在下拉菜单中选择刚刚导入的模型,即可将模型挂接在方块上。接下来,我们只需要进一步配置苹果方块的其他相关属性即可完成制作。
![](./images/10.2_components.png)
我们一起通过对应的JSON文件来考察各个组件的含义。
```json
{
"format_version": "1.10.0",
"minecraft:block": {
"description": {
"identifier": "tutorial_demo:apple"
},
"components": {
"minecraft:block_light_absorption": {
"value": 0
},
"minecraft:destroy_time": {
"value": 1.0
},
"minecraft:loot": {
"table": "loot_tables/custom_apple.json"
},
"netease:aabb": {
"clip": {
"max": [0.6875, 1.0, 0.6875],
"min": [0.3125, 0.375, 0.3125]
},
"collision": {
"max": [0.6875, 1.0, 0.6875],
"min": [0.3125, 0.375, 0.3125]
}
},
"netease:pathable": {
"value": true
},
"netease:render_layer": {
"value": "alpha"
},
"netease:solid": {
"value": false
}
}
}
}
```
`minecraft:block_light_absorption`是该方块的**不透明度****Opacity**),即光线吸收程度。该值越大光线在穿过时将减少得越多。我们希望这个方块不影响光线传播,所以将其改成和空气的不透明度保持一致。
`minecraft:destroy_time`是该方块的**硬度****Hardness**即方块的破坏基时间单位为秒s。实际的破坏时间将根据该基时间乘以对应的速度修饰符而计算产生。
`minecraft:loot`为该方块掉落的战利品表,我们将其设定为可以掉落苹果物品的战利品表。
![](./images/10.2_loot_table.png)
`netease:aabb`是只运行在中国版的组件,用于设定一个方块的**轴对其边界框****Axis-Aligned Bounding Box**,或译**轴对其包围盒**,简称**AABB**),即该方块的**碰撞****Collision**)体积和**裁剪****Clip**)体积。碰撞体积是该方块在世界中与实体相碰撞的体积,通常称为**碰撞箱****Collision Box**);裁剪体积则是用于设定方块的裁剪面,与游戏内的射线相交互的体积,比如用于玩家相机的射线和弹射物消失的轨道检测,通常称为**击中箱****Hitbox**)。
`netease:pathable`同样是中国版的组件,用于设定一个方块是否为可寻路方块。可寻路方块允许自己在生物寻路算法计算时被视作可践踏的方块。
`netease:render_layer`是中国版的组件,决定该方块的**渲染图层****Render Layer**)。方块的渲染图层是一系列预置的渲染方法,分别于不同的材质相绑定,用于决定一个方块是否透明、半透明、双面渲染等。
`netease:solid`是中国版的组件,决定该方块是否为**固体****Solid**)。在基岩版中固体属性决定着生物在方块中是否会受到窒息伤害。
我们将该方块设置为不吸光的非固体,边界框设定为和模型一致,渲染图层设置为透明,即可完成一个常规的非固体方块的设置。
![](./images/10.2_apple_in-game_1.png)
![](./images/10.2_apple_in-game_2.png)
我们进入游戏自测,可以看到苹果的渲染和模型都非常正常,正符合我们的预期!

View File

@@ -0,0 +1,230 @@
---
front: https://nie.res.netease.com/r/pic/20211104/69055361-2e7a-452f-8b1a-f23e1262a03a.jpg
hard: 高级
time: 15分钟
---
# 挑战:制作一个发光地灯
在本节中,我们完成一个挑战,制作一个发光地灯。可点击[方块模型资源](https://g79.gdl.netease.com/addonguide-10.zip)链接将模型资源下载到本地地灯方块模型在压缩包内的bbmodel文件夹里。
## 准备模型
我们在Blockbench中绘制一个发光地灯模型。
![](./images/10.3_model.png)
我们使用编辑器中的导入方块模型的功能导入该模型。
![](./images/10.3_model_import.png)
## 创建并修改配置
![](./images/10.3_block_config.png)
我们创建一个方块配置,然后通过在“**基础属性**”中添加`model``sound`的方式加入其地灯的模型和玻璃的声音。在“**行为包组件**”中重点设置“亮度”为大于0的值“吸光度”为0“渲染材质”为“全透明”。如果设置了非零吸光度则地灯将不能完全发出亮度等价的光而渲染材质如果没有设置为透明将出现黑色的阴影。
我们同时展示对应的JSON文件。行为包定义文件
```json
{
"format_version": "1.10.0",
"minecraft:block": {
"description": {
"identifier": "design:lamp"
},
"components": {
"minecraft:block_light_absorption": {
"value": 0
},
"minecraft:block_light_emission": {
"emission": 1.0
},
"minecraft:destroy_time": {
"value": 0.0
},
"minecraft:map_color": {
"color": "#ffffff"
},
"netease:render_layer": {
"value": "alpha"
},
"netease:tier": {
"destroy_special": false,
"digger": "pickaxe",
"level": 0
}
}
}
}
```
资源包定义文件:
```json
{
"format_version": [1, 1, 0],
"design:lamp": {
"netease_model": "design:lamp",
"sound": "glass"
}
}
```
纹理图集文件:
```json
{
"resource_pack_name": "vanilla",
"texture_name": "atlas.terrain",
"texture_data": {
"design:lamp": {
"textures": "textures/blocks/design/lamp"
}
}
}
```
方块模型几何:
```json
{
"format_version": "1.13.0",
"netease:block_geometry": {
"description": {
"identifier": "design:lamp",
"textures": ["design:lamp"],
"use_ao": false
},
"bones": [{
"name": "bone",
"pivot": [0, 0, 0],
"rotation": [0, 0, 0],
"cubes": [{
"origin": [-12.5, 1.5, 3.5],
"pivot": [0, 0, 0],
"rotation": [0, 0, 0],
"size": [9, 11, 9],
"uv": {
"down": {
"texture": 0,
"uv": [5.75, 6.25],
"uv_size": [-2.25, 2.25]
},
"east": {
"texture": 0,
"uv": [3.5, 0],
"uv_size": [2.25, 2.75]
},
"north": {
"texture": 0,
"uv": [3.5, 3.5],
"uv_size": [2.25, 2.75]
},
"south": {
"texture": 0,
"uv": [5.75, 5.75],
"uv_size": [2.25, 2.75]
},
"up": {
"texture": 0,
"uv": [5.75, 2.75],
"uv_size": [2.25, 2.25]
},
"west": {
"texture": 0,
"uv": [5.75, 0],
"uv_size": [2.25, 2.75]
}
}
}, {
"origin": [-12, 2, 4],
"pivot": [0, 0, 0],
"rotation": [0, 0, 0],
"size": [8, 10, 8],
"uv": {
"down": {
"texture": 0,
"uv": [4, 8.5],
"uv_size": [-2, 2]
},
"east": {
"texture": 0,
"uv": [8, 8],
"uv_size": [2, 2.5]
},
"north": {
"texture": 0,
"uv": [0, 7],
"uv_size": [2, 2.5]
},
"south": {
"texture": 0,
"uv": [8, 0],
"uv_size": [2, 2.5]
},
"up": {
"texture": 0,
"uv": [8, 5],
"uv_size": [2, 2]
},
"west": {
"texture": 0,
"uv": [8, 2.5],
"uv_size": [2, 2.5]
}
}
}, {
"origin": [-15, 0, 1],
"pivot": [0, 0, 0],
"rotation": [0, 0, 0],
"size": [14, 2, 14],
"uv": {
"down": {
"texture": 0,
"uv": [3.5, 3.5],
"uv_size": [-3.5, 3.5]
},
"east": {
"texture": 0,
"uv": [8, 7.5],
"uv_size": [3.5, 0.5]
},
"north": {
"texture": 0,
"uv": [8, 7],
"uv_size": [3.5, 0.5]
},
"south": {
"texture": 0,
"uv": [4, 8.5],
"uv_size": [3.5, 0.5]
},
"up": {
"texture": 0,
"uv": [0, 0],
"uv_size": [3.5, 3.5]
},
"west": {
"texture": 0,
"uv": [4, 9],
"uv_size": [3.5, 0.5]
}
}
}]
}]
}
}
```
语言本地化文件`zh_CN.lang`
```lang
tile.design:lamp.name=地灯
```
我们进入游戏查看效果。
![](./images/10.3_in-game.png)
可以看到,地灯的模型与预期一致,而且如期发出了最高亮度的光。