本篇教程的视频:
本篇教程源代码
本篇教程目标
查看源代码
注册语句
和前面的物品以及物品栏一样,我们也需要查看源代码来了解方块的注册方法。
首先,我们来查看Blocks这个类(注意是Minecraft包中的类),找一个方块,比如STONE。
1 2 3
| public static final Block STONE = register( "stone", BlockBehaviour.Properties.of().mapColor(MapColor.STONE).instrument(NoteBlockInstrument.BASEDRUM).requiresCorrectToolForDrops().strength(1.5F, 6.0F) );
|
这里我们先来看看BlockBehaviour.Properties这些东西,它和Item.Properties类似,是定义我们方块的属性的
of:创建属性的起始方法;
mapColor:定义方块在地图上的颜色;
instrument:当音符盒放在方块上时,能发出的声音;
requiresCorrectToolForDrops:方块是否需要正确的工具才能破坏,这个我们会在后面在战利品教程中讲;
strength:方块的破坏时间和抗爆强度
当然这也只是一部分,未来随着教程的进行我们也会看到一些其他的属性
注册方法
接下来,我们来看register方法。
1 2 3 4 5 6 7 8 9 10 11 12
| private static Block register(final String id, final BlockBehaviour.Properties properties) { return register(id, Block::new, properties); }
private static Block register(final String id, final Function<BlockBehaviour.Properties, Block> factory, final BlockBehaviour.Properties properties) { return register(vanillaBlockId(id), factory, properties); }
public static Block register(final ResourceKey<Block> id, final Function<BlockBehaviour.Properties, Block> factory, final BlockBehaviour.Properties properties) { Block block = (Block)factory.apply(properties.setId(id)); return Registry.register(BuiltInRegistries.BLOCK, id, block); }
|
register方法现在也有了很多的重载方法,和物品一样,用了Function来创建方块,添加方块的ID(不然就会出现Block id not set的错误)
vanillaBlockId方法与前面物品相似
1 2 3
| private static ResourceKey<Block> vanillaBlockId(final String name) { return ResourceKey.create(Registries.BLOCK, Identifier.withDefaultNamespace(name)); }
|
只不过这里用的是Registries.BLOCK,也就是方块的注册表
方块物品注册
方块这个东西它拥有两种状态,一个是你将方块放到这个世界中,那么它是方块;而当它在物品栏中时,它是物品(方块物品)
所以说方块两种状态都需要进行注册,现在我们来看Items中剩余的注册方法,还是以STONE为例。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| public static final Item STONE = registerBlock(Blocks.STONE);
private static Item registerBlock(final Block block) { return registerBlock(block, BlockItem::new); }
private static Item registerBlock(final Block block, final BiFunction<Block, Item.Properties, Item> itemFactory) { return registerBlock(block, itemFactory, new Item.Properties()); }
private static Item registerBlock(final Block block, final BiFunction<Block, Item.Properties, Item> itemFactory, final Item.Properties properties) { return registerItem( blockIdToItemId(block.builtInRegistryHolder().key()), p -> (Item)itemFactory.apply(block, p), properties.useBlockDescriptionPrefix().requiredFeatures(block.requiredFeatures()) ); }
private static Item registerItem(final ResourceKey<Item> key, final Function<Item.Properties, Item> itemFactory, final Item.Properties properties) { Item item = (Item)itemFactory.apply(properties.setId(key)); if (item instanceof BlockItem blockItem) { blockItem.registerBlocks(Item.BY_BLOCK, item); }
return Registry.register(BuiltInRegistries.ITEM, key, item); }
|
虽然它是层层叠叠,但最终还是回到了最后一个registerItem方法
而与一般物品不同的,方块物品是实例化BlockItem,而不是Item
另外在属性中,额外添加了useBlockDescriptionPrefix,这个方法就是让我们物品的名字直接沿用方块的名字,这样语言文件就不用写两遍了
其他的倒是都差不多
注册方块
创建ModBlocks类
首先我们创建一个ModBlocks类
1 2 3
| public class ModBlocks { }
|
方块注册方法
按照原版的注册方法,改一下其中的命名空间
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public static Block register(final String name, final Function<BlockBehaviour.Properties, Block> factory, final BlockBehaviour.Properties properties, boolean shouldRegisterItem) { ResourceKey<Block> id = ResourceKey.create(Registries.BLOCK, Identifier.fromNamespaceAndPath(TutorialMod.MOD_ID, name)); Block block = (Block)factory.apply(properties.setId(id));
if (shouldRegisterItem) { registerBlockItem(name, block); }
return Registry.register(BuiltInRegistries.BLOCK, id, block); }
public static Block register(final String name, final BlockBehaviour.Properties properties, boolean shouldRegisterItem) { return register(name, Block::new, properties, shouldRegisterItem); }
private static void registerBlockItem(String name, Block block) { ResourceKey<Item> id = ResourceKey.create(Registries.ITEM, Identifier.fromNamespaceAndPath(TutorialMod.MOD_ID, name)); BlockItem blockItem = new BlockItem(block, new Item.Properties().setId(id).useBlockDescriptionPrefix()); Registry.register(BuiltInRegistries.ITEM, id, blockItem); }
|
这里的第一个register方法是按照原版改的,不过加了一个布尔值,用来判断是否注册物品
因为在未来,有些方块的物品需要分离注册,比如作物和作物种子
第二个方法待会是我们用的,简化过的注册方法,直接实例化Block
第三个方法,是注册方块物品的,在注册方块的同时,它也会被调用,从而注册物品,这样我们就不用两头跑去注册方块物品了
注册方块
接下来我们来注册方块
1 2 3 4 5 6
| public static final Block ICE_ETHER_BLOCK = register("ice_ether_block", BlockBehaviour.Properties.of().strength(1.0f, 3.0f),true); public static final Block RAW_ICE_ETHER_BLOCK = register("raw_ice_ether_block", BlockBehaviour.Properties.ofFullCopy(Blocks.STONE),true); public static final Block ICE_ETHER_ORE = register("ice_ether_ore", BlockBehaviour.Properties.of().strength(1.0f, 3.0f).requiresCorrectToolForDrops(),true);
|
这里我们注册了3个方块,其中,第二个我们直接使用原版STONE的属性,最后一个我们加上了requiresCorrectToolForDrops方法
至于这两个我们会在下一篇教程中详细展开
初始化注册方法
1 2 3
| public static void register() { TutorialMod.LOGGER.info("Registering Mod Blocks for " + TutorialMod.MOD_ID); }
|
那么这个方法同样需要在主类调用
添加到物品栏
记得将我们的方块添加到物品栏
1 2 3
| output.accept(ModBlocks.ICE_ETHER_BLOCK); output.accept(ModBlocks.RAW_ICE_ETHER_BLOCK); output.accept(ModBlocks.ICE_ETHER_ORE);
|
数据文件
方块状态文件
方块的具体状态是由方块状态文件来决定的,比如按钮的按下状态、门的开关状态、楼梯的各种形态等等
具体可以看原版的方块状态文件,这里我们就简单写一下方块状态文件
这些文件都是放在assets/tutorial/blockstates/文件夹下的
ice_ether_block.json
1 2 3 4 5 6 7
| { "variants": { "": { "model": "tutorial:block/ice_ether_block" } } }
|
ice_ether_ore.json
1 2 3 4 5 6 7
| { "variants": { "": { "model": "tutorial:block/ice_ether_ore" } } }
|
raw_ice_ether_block.json
1 2 3 4 5 6 7
| { "variants": { "": { "model": "tutorial:block/raw_ice_ether_block" } } }
|
这个文件是assets/tutorial/blockstates/raw_ice_ether_block.json
方块状态文件里的model就是我们的模型文件
方块模型文件
方块模型文件的路径是assets/tutorial/models/block/
ice_ether_block.json
1 2 3 4 5 6
| { "parent": "minecraft:block/cube_all", "textures": { "all": "tutorial:block/ice_ether_block" } }
|
ice_ether_ore.json
1 2 3 4 5 6
| { "parent": "minecraft:block/cube_all", "textures": { "all": "tutorial:block/ice_ether_ore" } }
|
raw_ice_ether_block.json
1 2 3 4 5 6
| { "parent": "minecraft:block/cube_all", "textures": { "all": "tutorial:block/raw_ice_ether_block" } }
|
这里使用的是cube_all这个模型,即所有的面都是同一个材质
all代表的是材质文件
材质文件
文件路径是src/main/resources/assets/tutorial/textures/block/xxx.png
和你的方块注册名一样
物品描述文件
现在的版本中,可以不写方块物品的模型文件了,但我们之前讲过的物品描述文件(客户端物品)还得写
文件路径依旧是assets/tutorial/items/
ice_ether_block.json
1 2 3 4 5 6
| { "model": { "type": "minecraft:model", "model": "tutorial:block/ice_ether_block" } }
|
ice_ether_ore.json
1 2 3 4 5 6
| { "model": { "type": "minecraft:model", "model": "tutorial:block/ice_ether_ore" } }
|
raw_ice_ether_block.json
1 2 3 4 5 6
| { "model": { "type": "minecraft:model", "model": "tutorial:block/raw_ice_ether_block" } }
|
都指向我们方块的模型文件
语言文件
1 2 3 4 5
| { "block.tutorial.ice_ether_block": "Ice Ether Block", "block.tutorial.ice_ether_ore": "Ice Ether Ore", "block.tutorial.raw_ice_ether_block": "Raw Ice Ether Block" }
|
与物品的类似,不过它的前缀是block
接下来我们即可以进入游戏进行测试了