欢迎你来阅读本篇自定义方块教程!Minecraft是由无穷无尽的方块所组成的,因此在模组以及地图制作中,将难免遇到各种各样新的方块需求。本篇教程将带你入门基岩版自定义方块,了解如何在基岩版添加一个富有特色的方块。
在阅读本篇教程之前,请确保你已经能够创建一个行为包和资源包,若还不能,请先阅读开始之前;包的构建;运行、调试与导出页面以学习行为包的基础制作。此外,为简化本篇的篇幅,请先提前阅读Tutorial:制作附加包/物品以熟悉自定义内容的一些必要工具和思路。本教程将假设你已经了解了自定义物品的制作方法。
引言[编辑]
不同版本之间的差异[编辑]
自定义方块亦有三个分水岭版本存在:
1.10
,加入了对自定义方块的支持;1.16.100
,加入了非常多全新的方块组件,然而它们都是实验性的;1.19.X
,令一些实用的方块走出了实验性玩法,并加入了一些新特性。
请按照自己的需求选择需要的版本。我们推荐你使用稳定的版本和稳定的方块组件,1.19.70之后的组件已趋于稳定。
1.10至1.16.100的自定义方块编写[编辑]
你需要首先创建一个行为包和资源包,创建方法不过多赘述。
行为包部分[编辑]
在行为包目录下,创建一个名为blocks
的文件夹,并在该文件夹下创建一个文件my_custom_block.block.json
。你可以看到,这步骤和自定义物品是大同小异的。
- 行为包名称或其内部ID
- blocks
- my_custom_block.block.json
- manifest.json
- pack_icon.png
- blocks
我们也可以照葫芦画瓢地给出一个最基础的自定义方块的定义:
{
"format_version": "1.16.0",
"minecraft:block": {
"description": {
"identifier": "test:my_custom_block"
}
}
}
相信如果你已经学会了自定义物品的话,理解这段代码对你来说应该不是什么难事。这里需要指出的一点是,Mojang在1.15时曾对方块组件做出过更新并修改了方块组件所能接受的值。本教程基于1.16.0。如果你需要1.15以前的写法可以参考以下内容:
现在我们不妨直入主题来为我们的方块加入自定义组件吧!当然,旧版本的自定义方块的组件也非常的少,但你已经可以用它们来实现最基础的效果了。旧版本的方块组件有以下几个可用:
minecraft:destroy_time
- 指定破坏时间。minecraft:block_light_absorption
- 指定方块减弱的光照强度。minecraft:block_light_emission
- 指定方块发出的光照强度。minecraft:explosion_resistance
- 指定方块的爆炸抗性。minecraft:friction
- 指定方块的摩擦力。minecraft:loot
- 指定方块的掉落物。minecraft:map_color
- 指定方块在地图上显示的颜色。
例如,如果我们希望自定义方块的光照等级是15,并且在被挖掉之后掉落钓鱼的战利品,我们可以写成:
{
"format_version": "1.16.0",
"minecraft:block": {
"description": {
"identifier": "test:my_custom_block"
},
"components": {
"minecraft:block_light_emission": 1.0, // 旧版本下该值的范围为0.0-1.0
"minecraft:loot": "loot_tables/gameplay/fishing.json"
}
}
}
以下是这段代码的解释:
minecraft:block_light_emission
:方块光照强度,它支持一个0.0-1.0
的浮点数,值越大则光照越强。minecraft:loot
:战利品表,当该方块被挖掘后,调用其指定的战利品表。
资源包部分[编辑]
自定义方块的资源包部分比较复杂。你可能需要以下文件(即粗体部分),请先提前创建:
- 资源包名称或其内部ID
- texts
- en_US.lang
- zh_CN.lang
- textures
- blocks
- (方块贴图1).png
- (方块贴图2).png
- ...
- terrain_texture.json(链接短ID和贴图)
- flipbook_textures.json(当你需要一个要涉及到动态贴图的方块时创建,例如海晶灯)
- blocks
- blocks.json(链接ID和短ID)
- manifest.json
- pack_icon.png
- texts
blocks.json[编辑]
我们先从blocks.json
入手。需要注意一点,自定义方块有三种显示模式:六面全同、分顶面底面和侧面、分顶底东西南北。举两个简单的例子,我们知道泥土六个面是完全一样的,这是利用了最简单的六面全同模式;草方块的顶面是绿色的草贴图,底面是泥土贴图,而侧面是覆盖了一层草的贴图,这就是分顶底侧面。在入手之前请先想好自己的方块应该是什么样的,再动手。下面是blocks.json
的基本格式和三个模式的方块指定方法:
{
"方块ID": { "textures": "短ID", "sound": "音效" }, // 六面全同
"方块ID": { "textures": { "down": "短ID1", "side": "短ID2", "up": "短ID3" }, "sound": "音效" }, // 分顶底侧面
"方块ID": { "textures": { "down": "短ID1", "up": "短ID2", "north": "短ID3", "south": "短ID4", "west": "短ID5", "east": "短ID6" }, "sound": "音效" } // 分顶底东西南北
}
其中音效可以是原版的方块音效,在被放置、被踩踏以及被破坏后将播放对应方块的音效,你可以查看原版的blocks.json
来查看有哪些内容是能够允许的。以下是几种比较常用的音效:
stone
:石头质音效(例如石头、混凝土);glass
:玻璃质音效(例如玻璃、荧石);gravel
:泥质音效(例如泥土、沙砾);wood
:木质音效(例如木板、木头);cloth
:布质音效(例如羊毛、地毯);grass
:草质音效(例如草方块、树叶);metal
:金属质音效(例如铁块、金块)。
举个例子,如果我希望加入一种新的木板,它应该是六面全同,使用木质音效的,因此可以写为:
{
"test:my_custom_block": { "textures": "my_custom_block", "sound": "wood" }
}
terrain_texture.json[编辑]
接着我们来看terrain_texture.json
。我们在blocks.json
中指定了短ID,该文件就是将短ID和实际的贴图文件链接起来的。假设我们已经在textures/blocks
文件夹里面放入了一个my_custom_planks.png
的文件,我们便可以如此指代:
{
"resource_pack_name": "vanilla",
"texture_name": "atlas.terrain",
"padding": 8,
"num_mip_levels": 4,
"texture_data": {
"my_custom_block": { "textures": [ "textures/blocks/my_custom_planks" ] },
"短ID": { "textures": [ "贴图路径" ] },
...
}
}
其中前4行是什么你并不需要关心,你需要关心的只是其中的texture_data
。它的一般格式也在上面的代码中提出,你可以看到短ID就是如此链接到实际贴图的。
动态贴图[编辑]
本段落仍需完善。 |
如果你的方块需要用到动态贴图,你可能需要用到flipbook_texture.json
。动态贴图的用法可自行参考原版写法。
翻译文本[编辑]
和自定义物品类似,你也需要一个翻译文件来指定它们显示出的名字。打开en_US.lang
,输入以下内容:
tile.test:my_custom_block.name=My Custom Block
如你所见,方块的翻译文本格式为tile.方块ID.name
。同理地,在zh_CN.lang
输入以下内容:
tile.test:my_custom_block.name=我的自定义方块
至此,你的方块编写就大功告成啦!当然了,本教程也会介绍新版本组件的简单应用,详见下文。
1.19.60及更高版本的自定义方块编写[编辑]
行为包部分[编辑]
1.19.60版本后又进一步的开放了部分组件。和高版本物品组件是几乎全新不同,高版本的方块组件是基于低版本组件的。1.19.60之后有下列组件可以不开启实验性玩法使用:
minecraft:geometry
- 指定方块模型。minecraft:material_instances
- 将模型文件中的面或渲染映射到实际的纹理。minecraft:collision_box
- 指定方块的碰撞箱。minecraft:crafting_table
- 设置与方块互动时打开一个合成界面。minecraft:display_name
- 指定方块的名称。minecraft:placement_filter
- 设置方块被放置时应满足的条件。minecraft:selection_box
- 指定方块的击中箱。
同时,旧版组件大多数都经过了重命名,这里不再详述。
资源包部分[编辑]
高版本方块的流程和低版本方块的流程可以说是几乎完全相同的。但特别地,当你指定了minecraft:material_instance
的texture
参数时,写法可能会有一些小变化。在下面的范例中你就可以知道了。
方块状态的设定[编辑]
方块状态(Block States)是指定方块所处状态的一种重要手段,例如半砖是上半砖还是下半砖、羊毛的颜色、按钮的朝向等等,这些方块都有相同的ID,但是它们所处的状态不一样。在自定义方块中你可以利用description
中的states
指定方块所处的方块状态,并利用permutations
来另行指代不同方块状态下采用的不同组件。以下是微软文档中给出的一个方块状态与置换的范例:
{
"format_version": "1.19.40",
"minecraft:block": {
"description": {
"identifier": "custom:lamp_block",
"states": {
"custom:is_lit": [ true, false ]
}
},
"permutations": [
{
"condition": "query.block_state('custom:is_lit') == true",
"components": {
"minecraft:light_emission": 15
}
},
{
"condition": "query.block_state('custom:is_lit') == false",
"components": {
"minecraft:light_emission": 0
}
}
],
"components": {
"minecraft:friction": 0.6,
"minecraft:map_color": "#00ff00"
}
}
}
对这段代码做一些必要的解释:
states
:方块状态,指定方块可能具有的状态。在这里,该方块被指定了具有custom:is_lit
的方块状态,并支持两个值,分别为true
和false
。permutations
:方块置换,指定在满足特定的条件(condition
)下该方块所具有的组件。我们可以看到,condition
的检测条件为query.block_state('custom:is_lit') == true
,这是用于检测该方块所处状态的Molang,当custom:is_lit
方块状态为true
时将使用组件"minecraft:light_emission": 15
,即光照亮度为15级。下面的条目也是同理的。components
:方块组件,指定方块所具有的通用特性。
你可以使用命令/setblock
或/fill
来放置这些具有自定义特性的方块。
关于方块状态和置换,你可以查看更加详细的微软文档。
方块性状的设定[编辑]
一些范例[编辑]
无法被破坏和炸毁的泥土[编辑]
如果你希望泥土不再能被破坏,何不以假乱真来做一个新方块呢?请记住,原版物品和方块都是不能更改的,因此如果你希望更改原版方块,请立即放弃这种想法,自己做个新方块才是更好的选择。
要实现这点很简单,我们的核心要素在于“无法破坏”和“无法炸毁”两点,这分别可以用minecraft:destructible_by_mining
和minecraft:destructible_by_explosion
来解决。因此可以用下面的行为包代码:
- 行为包/blocks/dirt.block.json
{
"format_version": "1.19.40",
"minecraft:block": {
"description": {
"identifier": "wiki:dirt"
},
"components": {
"minecraft:destructible_by_explosion": false,
"minecraft:destructible_by_mining": false
}
}
}
资源包方面,我们可以偷个懒,直接调用原版的方块路径:
- 资源包/blocks.json
{
"wiki:dirt": { "textures": "dirt", "sound": "gravel" }
}
可以调用原版的贴图有一个条件,就是原版的这个对应短ID不能链接到多个纹理,一旦链接到有多个纹理的短ID,就会出现紫黑块贴图错误。如果不能直接偷懒用原版的短ID,就需要再用terrain_texture.json
来链接到贴图上(当然这个贴图也是可以直接链接原版的)。最后搞定翻译即可:
- 资源包/texts/en_US.lang
tile.wiki:dirt.name=Dirt
- 资源包/texts/zh_CN.lang
tile.wiki:dirt.name=泥土
然后,你就可以获得一个以假乱真,但是怎么炸也炸不坏的泥土了!
会发光的玻璃[编辑]
想不想要一种可以自发光的玻璃?我们当然可以实现!想想玻璃的一些需求要素:
- 透明,这可以用
minecraft:material_instance
来实现; - 无掉落物,这可以用
minecraft:loot
掉落一个空的战利品表来实现; - 发光,这可以用
minecraft:light_emission
来实现; - 还原玻璃的硬度(0.3)和爆炸抗性(0.3),用
minecraft:destructible_by_mining
和minecraft:destructible_by_explosion
来实现。
因此,行为包代码也就呼之欲出了。
- 行为包/blocks/glass.block.json
{
"format_version": "1.19.40",
"minecraft:block": {
"description": {
"identifier": "wiki:scene_block_glass"
},
"components": {
"minecraft:material_instances": { "*": { "render_method": "blend" } },
"minecraft:destructible_by_explosion": { "explosion_resistance": 0.3 },
"minecraft:destructible_by_mining": { "seconds_to_destroy": 0.3 },
"minecraft:light_dampening": 0,
"minecraft:light_emission": 15,
"minecraft:loot": "loot_tables/empty.json"
}
}
}
一些基本解释:
minecraft:material_instance
:令方块为透明渲染。*
代表所有面都按照透明的方式渲染。minecraft:light_dampening
:对于透明渲染的方块而言,如果不设置这个值,它本质上是不透明方块,一是会导致草方块的变化,二是会导致方块与方块之间在底面出现很重的阴影,对于“发光玻璃”而言,这并不是我们希望的结果。
资源包不做过多解释,这是很简单的。
能穿透又摸不到的假方块[编辑]
假方块!在很久以前,基岩版的按钮漏洞导致其在某个特殊值下会显示为整个方块,而其又没有碰撞箱,是可以穿过的,因此称之为假方块。虽然这是一个漏洞,但今天我们却能实打实的做一个真正的假方块出来了!要想实现假方块,我们只需要考虑碰撞箱和击中箱的问题。这可以利用minecraft:collision_box
和minecraft:selection_box
来解决。我们只需要完全取消掉它的碰撞箱,就可以让它是可被穿过的:
- 行为包/blocks/fake_oak_planks.block.json
{
"format_version": "1.19.60",
"minecraft:block": {
"description": {
"identifier": "wiki:fake_oak_planks"
},
"components": {
"minecraft:collision_box": false
}
}
}
这将禁用它的碰撞箱,成为可穿过的方块;而如果再引入一个击中箱:
- 行为包/blocks/fake_oak_planks.block.json
{
"format_version": "1.19.60",
"minecraft:block": {
"description": {
"identifier": "wiki:fake_oak_planks"
},
"components": {
"minecraft:collision_box": false,
"minecraft:selection_box": false
}
}
}
这甚至会让玩家无法选中这个方块(包括创造模式玩家)!如果放到了错误的地方,你就需要用/setblock
来解决啦。
自定义台阶[编辑]
假设我们在抗爆泥土上再进一步,要实现不可破坏的台阶,显然这是一种不完整方块。对于台阶,我们需要考虑以下几点:
- 方块不是完整方块,必须使用特定的方块模型。方块模型需要在Blockbench里自行绘制,假设我们现在已经拥有了
geometry.slab_up
和geometry.slab_down
两个模型。指定模型可以由minecraft:geometry
来承担。 - 其碰撞箱和击中箱都必须是普通方块的一半;
- 因为调用了自定义模型,这个方块的面的表达已经不再能用普通的三种情况来代替,必须使用
minecraft:material_instance
来选择性地指定面的贴图。
基于这样的考虑,我们给出以下参考代码:
- 行为包/blocks/cobblestone_slab_up.block.json
{
"format_version": "1.19.60",
"minecraft:block": {
"description": {
"identifier": "wiki:cobblestone_slab_up"
},
"components": {
"minecraft:destructible_by_explosion": false,
"minecraft:destructible_by_mining": false,
"minecraft:collision_box": { "origin": [ -8, 8, -8 ], "size": [ 16, 8, 16 ] },
"minecraft:selection_box": { "origin": [ -8, 8, -8 ], "size": [ 16, 8, 16 ] },
"minecraft:geometry": { "identifier": "geometry.slab_up" },
"minecraft:material_instances": { "*": { "texture": "cobblestone" } }
}
}
}
关于碰撞箱和选择箱的写法,见对应条目。如果我们需要把两种台阶合在一起写,就可以利用前面的方块状态的设定的内容来合并:
- 行为包/blocks/cobblestone_slab.block.json
{
"format_version": "1.19.70",
"minecraft:block": {
"description": {
"identifier": "wiki:cobblestone_slab",
"states": { "vertical_half": [ "top", "bottom" ] }
},
"components": {
"minecraft:destructible_by_explosion": false,
"minecraft:destructible_by_mining": false,
"minecraft:material_instances": { "*": { "texture": "cobblestone" } }
},
"permutations": [
{
"condition": "query.block_state('vertical_half') == 'top'",
"components": {
"minecraft:collision_box": { "origin": [ -8, 8, -8 ], "size": [ 16, 8, 16 ] },
"minecraft:selection_box": { "origin": [ -8, 8, -8 ], "size": [ 16, 8, 16 ] },
"minecraft:geometry": { "identifier": "geometry.slab_up" }
}
},
{
"condition": "query.block_state('vertical_half') == 'bottom'",
"components": {
"minecraft:collision_box": { "origin": [ -8, 0, -8 ], "size": [ 16, 8, 16 ] },
"minecraft:selection_box": { "origin": [ -8, 0, -8 ], "size": [ 16, 8, 16 ] },
"minecraft:geometry": { "identifier": "geometry.slab_down" }
}
}
]
}
}
最后利用/setblock
等命令对方块状态进行控制。是不是很有意思?
关于资源包的问题,事实上你看到了minecraft:material_instances
这个组件指定了texture
,这其实就是blocks.json
中的那个短ID,在方块中也是存在短ID迁移到行为包中的现象的。因此,blocks.json
就可以进行简化:
- 资源包/blocks.json
{
"wiki:cobblestone_slab": { "sound": "stone" }
}
即忽略掉texture
参数。至于terrain_texture.json
,其实行为包代码也偷了个懒,直接调用了原版的cobblestone
纹理,因此根本无需再次更改!