本篇教程的视频:

本篇教程源代码

GitHub地址:TutorialMod-Block-1.21

查看源代码

方块

和前面的物品以及物品栏一样,我们也需要查看源代码来了解方块的注册方法。

首先,我们来查看Blocks这个类(注意是Minecraft包中的类),找一个方块,比如STONE

1
public static final Block STONE = Blocks.register("stone", new Block(AbstractBlock.Settings.create().mapColor(MapColor.STONE_GRAY).instrument(NoteBlockInstrument.BASEDRUM).requiresTool().strength(1.5f, 6.0f)));

同样的,我们先不看里面填的参数,我们来看register方法。

1
2
3
public static Block register(String id, Block block) {
return Registry.register(Registries.BLOCK, id, block);
}

那么相比较而言,方块就只有一个方法,而且这个方法也很简单,就是调用Registryregister方法。

不过这里中间的参数是String,我们也可以写Identifier

另外,你可能会发现其他的注册方法,有些是为特殊方块单独拿出来的,比如楼梯、蜡烛、盆栽等等。这里所讲解的为最简单的方块注册方法,其他的注册可以自行研究

方块物品

方块这个东西它拥有两种状态,一个是你将方块放到这个世界中,那么它是方块;而当它在物品栏中时,它是物品(方块物品)

所以说方块两种状态都需要进行注册,现在我们来看Items中剩余的注册方法,还是以STONE为例。

1
public static final Item STONE = Items.register(Blocks.STONE);

先来看register方法,也是叠了好几层

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public static Item register(Block block) {
return Items.register(new BlockItem(block, new Item.Settings()));
}

public static Item register(BlockItem item) {
return Items.register(item.getBlock(), (Item)item);
}

public static Item register(Block block, Item item) {
return Items.register(Registries.BLOCK.getId(block), item);
}

public static Item register(Identifier id, Item item) {
return Items.register(RegistryKey.of(Registries.ITEM.getKey(), id), item);
}

public static Item register(RegistryKey<Item> key, Item item) {
if (item instanceof BlockItem) {
((BlockItem)item).appendBlocks(Item.BLOCK_ITEMS, item);
}
return Registry.register(Registries.ITEM, key, item);
}

而最后,我们可以看到,register方法最终调用了Registryregister方法,和我们的物品注册方法是一样的

唯一不同之处在于,在一开始时,实例化的不是Item,而是BlockItem,这个类是用于方块物品的

至于最后的appendBlocks方法,这个方法是用于将方块物品添加到Item.BLOCK_ITEMS这个列表中的,这个列表是用于存放所有的方块物品的;实际上这个不写也没有关系

方块注册

创建ModBlocks类

1
2
3
public class ModBlocks {

}

方块注册方法

按照原版的注册方法,改一下其中的命名空间即可

1
2
3
public static Block register(String id, Block block) {
return Registry.register(Registries.BLOCK, Identifier.of(TutorialMod.MOD_ID, id), block);
}

方块物品注册方法

虽然原版叠了好几层,但还是可以整合一下

1
2
3
4
5
6
public static void registerBlockItems(String id, Block block) {
Item item = Registry.register(Registries.ITEM, Identifier.of(TutorialMod.MOD_ID, id), new BlockItem(block, new Item.Settings()));
if (item instanceof BlockItem) {
((BlockItem)item).appendBlocks(Item.BLOCK_ITEMS, item);
}
}

而这个方法,可以直接在register方法(上面那个)中调用

1
2
3
4
public static Block register(String id, Block block) {
registerBlockItems(id, block);
return Registry.register(Registries.BLOCK, Identifier.of(TutorialMod.MOD_ID, id), block);
}

这样我们注册方块的同时,方块物品也注册了,然后你就不用到物品注册中再写一次了

不过,在后期的教程中,我们还会碰到没有方块物品的方块(比如作物方块),那么这个时候,我们就只需要注册方块即可

注册方块

在开始之前,我们还是先看看STONE里面的参数

1
new Block(AbstractBlock.Settings.create().mapColor(MapColor.STONE_GRAY).instrument(NoteBlockInstrument.BASEDRUM).requiresTool().strength(1.5f, 6.0f))

这里我只截取后面部分,这里使用的是AbstractBlock.Settings,这个类是用于设置方块的属性的

create方法是创建方块的属性,你也可以使用copy方法,直接将原版方块的属性复制过来

mapColor是设置方块的显示在地图上的颜色

instrument是设置音符盒放在它上面时发出的声音

requiresTool是设置方块是否需要工具才能破坏

strength是设置方块的硬度和爆炸抗性

其他的方块还有很多属性,这里就不一一介绍了,具体的属性可以自行查阅;那我们现在来注册几个方块

1
2
3
public static final Block ICE_ETHER_BLOCK = register("ice_ether_block", new Block(AbstractBlock.Settings.create().strength(3.0f, 3.0f)));
public static final Block ICE_ETHER_ORE = register("ice_ether_ore", new Block(AbstractBlock.Settings.create().strength(4.5f, 6.0f)));
public static final Block RAW_ICE_ETHER_BLOCK = register("raw_ice_ether_block", new Block(AbstractBlock.Settings.create().strength(3.0f, 3.0f)));

这里我们就简单设置一下硬度和爆炸抗性,requireTool这个暂时不写,因为写了这个以后,编写掉落物的文件时,还得写Tag,这个我们在掉落物教程中再讲

初始化方法

初始化方法不要忘记

1
2
3
public static void registerModBlocks() {
TutorialMod.LOGGER.info("Registering Blocks");
}

然后在主类中调用这个方法

1
ModBlocks.registerModBlocks();

整体代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class ModBlocks {
public static final Block ICE_ETHER_BLOCK = register("ice_ether_block", new Block(AbstractBlock.Settings.create().strength(3.0f, 3.0f)));
public static final Block ICE_ETHER_ORE = register("ice_ether_ore", new Block(AbstractBlock.Settings.create().strength(4.5f, 6.0f)));
public static final Block RAW_ICE_ETHER_BLOCK = register("raw_ice_ether_block", new Block(AbstractBlock.Settings.create().strength(3.0f, 3.0f)));
public static void registerBlockItems(String id, Block block) {
Item item = Registry.register(Registries.ITEM, Identifier.of(TutorialMod.MOD_ID, id), new BlockItem(block, new Item.Settings()));
if (item instanceof BlockItem) {
((BlockItem)item).appendBlocks(Item.BLOCK_ITEMS, item);
}
}
public static Block register(String id, Block block) {
registerBlockItems(id, block);
return Registry.register(Registries.BLOCK, Identifier.of(TutorialMod.MOD_ID, id), block);
}
public static void registerModBlocks() {
TutorialMod.LOGGER.info("Registering Blocks");
}
}

加入物品栏

我们将方块放到物品栏中,这样我们就可以在物品栏中看到我们的方块了

1
2
3
entries.add(ModBlocks.ICE_ETHER_BLOCK);
entries.add(ModBlocks.ICE_ETHER_ORE);
entries.add(ModBlocks.RAW_ICE_ETHER_BLOCK);

数据文件

所有文件的文件名都要和你的注册名一样,负责就会报错

方块状态文件

方块的具体状态是由方块状态文件来决定的,比如按钮的按下状态、门的开关状态、楼梯的各种形态等等

具体可以看原版的方块状态文件,这里我们就简单一下方块状态文件

1
2
3
4
5
6
7
{
"variants": {
"": {
"model": "tutorialmod:block/ice_ether_block"
}
}
}

这个文件是src/main/resources/assets/tutorialmod/blockstates/ice_ether_block.json

1
2
3
4
5
6
7
{
"variants": {
"": {
"model": "tutorialmod:block/ice_ether_ore"
}
}
}

这个文件是src/main/resources/assets/tutorialmod/blockstates/ice_ether_ore.json

1
2
3
4
5
6
7
{
"variants": {
"": {
"model": "tutorialmod:block/raw_ice_ether_block"
}
}
}

这个文件是src/main/resources/assets/tutorialmod/blockstates/raw_ice_ether_block.json

方块状态文件里的model就是我们的模型文件

模型文件

这里我们也简单一下模型文件,使用6面皆为同一个材质的方块模型文件

1
2
3
4
5
6
{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "tutorialmod:block/ice_ether_block"
}
}

这个文件是src/main/resources/assets/tutorialmod/models/block/ice_ether_block.json

1
2
3
4
5
6
{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "tutorialmod:block/ice_ether_ore"
}
}

这个文件是src/main/resources/assets/tutorialmod/models/block/ice_ether_ore.json

1
2
3
4
5
6
{
"parent": "minecraft:block/cube_all",
"textures": {
"all": "tutorialmod:block/raw_ice_ether_block"
}
}

这个文件是src/main/resources/assets/tutorialmod/models/block/raw_ice_ether_block.json

这里使用的是cube_all这个模型,所有的面都是同一个材质

all代表的是材质文件

材质文件

文件路径是src/main/resources/assets/tutorialmod/textures/block/xxx.png

和你的方块注册名一样

语言文件

1
2
3
4
5
{
"block.tutorialmod.ice_ether_block": "Ice Ether Block",
"block.tutorialmod.ice_ether_ore": "Ice Ether Ore",
"block.tutorialmod.raw_ice_ether_block": "Raw Ice Ether Block"
}