本篇教程的视频:
本篇教程源代码
介绍
木头
作为我们在游戏初期必不可少的资源,想必大家都很熟悉了吧
本篇教程我们将会增加原木
、木头
、木板
和树叶
,为之后的树
以及树的世界生成
做准备,毕竟树最基本的组成部分就是原木和树叶
木头其实有很多,有原木
、去皮原木
、木头
、去皮木头
这四类,衍生的还有木板
木头和原木的区别在于其是否六面皆为树皮纹理,当然,自然生成的只有原木
查看源代码
我们来看看原版和木头有关的注册方法
原木
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public static final Block OAK_LOG = register("oak_log", createLogBlock(MapColor.OAK_TAN, MapColor.SPRUCE_BROWN));
public static final Block STRIPPED_OAK_LOG = register("stripped_oak_log", createLogBlock(MapColor.OAK_TAN, MapColor.OAK_TAN));
public static Block createLogBlock(MapColor topMapColor, MapColor sideMapColor) { return new PillarBlock( AbstractBlock.Settings.create() .mapColor(state -> state.get(PillarBlock.AXIS) == Direction.Axis.Y ? topMapColor : sideMapColor) .instrument(NoteBlockInstrument.BASS) .strength(2.0F) .sounds(BlockSoundGroup.WOOD) .burnable() ); }
|
我们可以看到,其注册方法也是和前面一样的,只是后面返回的block
用一个createLogBlock
方法提炼出来了
这个方法返回的是一个PillarBlock
,这个类是一个柱状方块,也就是我们常见的原木,上下两面的材质和侧面的材质是不一样的
这里的设置多了一个burnable
方法,这个方法是用来设置方块是否可以被火点燃的,因为木头是可燃物嘛
去皮原木同理
木头
1 2 3 4 5 6 7 8 9 10 11 12 13
| public static final Block OAK_WOOD = register( "oak_wood", new PillarBlock( AbstractBlock.Settings.create().mapColor(MapColor.OAK_TAN).instrument(NoteBlockInstrument.BASS).strength(2.0F).sounds(BlockSoundGroup.WOOD).burnable() ) );
public static final Block STRIPPED_OAK_WOOD = register( "stripped_oak_wood", new PillarBlock( AbstractBlock.Settings.create().mapColor(MapColor.OAK_TAN).instrument(NoteBlockInstrument.BASS).strength(2.0F).sounds(BlockSoundGroup.WOOD).burnable() ) );
|
木头和原木的注册方法基本一样,也是实例化一个PillarBlock
不过木头明明是六面材质相同的方块,为什么这里还是PillarBlock
呢?(说实话我也不知道)
木板
1 2 3 4 5 6
| public static final Block OAK_PLANKS = register( "oak_planks", new Block( AbstractBlock.Settings.create().mapColor(MapColor.OAK_TAN).instrument(NoteBlockInstrument.BASS).strength(2.0F, 3.0F).sounds(BlockSoundGroup.WOOD).burnable() ) );
|
木板就常规多了,就是一个普通的方块,不过这里也是burnable
的
树叶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| public static final Block OAK_LEAVES = register("oak_leaves", createLeavesBlock(BlockSoundGroup.GRASS));
public static Block createLeavesBlock(BlockSoundGroup soundGroup) { return new LeavesBlock( AbstractBlock.Settings.create() .mapColor(MapColor.DARK_GREEN) .strength(0.2F) .ticksRandomly() .sounds(soundGroup) .nonOpaque() .allowsSpawning(Blocks::canSpawnOnLeaves) .suffocates(Blocks::never) .blockVision(Blocks::never) .burnable() .pistonBehavior(PistonBehavior.DESTROY) .solidBlock(Blocks::never) ); }
|
树叶的注册方法和原木类似,用一个createLeavesBlock
方法提炼出来
nonOpaque
方法是用来设置方块是否为实心的,显然树叶是空心的,所以这里是nonOpaque
allowsSpawning
方法是用来设置方块是否允许生物生成在其上的,这里的判断方法是canSpawnOnLeaves
suffocates
方法是用来设置方块是否会使生物窒息的,这里设置的是never
,也就是不会,方块默认是会使生物窒息的
blockVision
方法是用来设置方块是否会阻挡视线的,这里也是不会
pistonBehavior
方法是用来设置方块被活塞推动时的行为,这里是DESTROY
,也就是会被破坏
solidBlock
方法是用来设置方块是否为实心方块的,这里也不是
树叶额外设置的方法比较多,当然,如果你不想写这么一串,就直接用这里的方法或者copy
原有方块
其他东西
原木与去皮原木
这里我们再往下挖掘一点,来看看原木
与去皮原木
有什么关系
我们可以在AxeItem
中找到这样一段代码
1 2 3 4 5
| protected static final Map<Block, Block> STRIPPED_BLOCKS = new Builder<Block, Block>() .put(Blocks.OAK_WOOD, Blocks.STRIPPED_OAK_WOOD) .put(Blocks.OAK_LOG, Blocks.STRIPPED_OAK_LOG) ... .build();
|
我们可以看到,这里是一个Map
,用来存储原木
与去皮原木
的对应关系
但是这玩意是protected
的,根据我们之前的经验,用Mixin
吧
不过,其实Fabric
已经有轮子(API
)了,那我们就用呗,虽然Fabric
的轮子没有Forge
多,但有就用好了
可燃物方块
再挖一挖(其实能挖的东西很多很多),我们区看看这种可燃物方块的燃烧属性是怎么样的,我们可以在FireBlock
中找到这样一段代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public static void registerDefaultFlammables() { FireBlock fireBlock = (FireBlock)Blocks.FIRE; fireBlock.registerFlammableBlock(Blocks.OAK_PLANKS, 5, 20);
fireBlock.registerFlammableBlock(Blocks.OAK_LOG, 5, 5);
fireBlock.registerFlammableBlock(Blocks.STRIPPED_OAK_LOG, 5, 5);
fireBlock.registerFlammableBlock(Blocks.STRIPPED_OAK_WOOD, 5, 5);
fireBlock.registerFlammableBlock(Blocks.OAK_WOOD, 5, 5);
fireBlock.registerFlammableBlock(Blocks.OAK_LEAVES, 30, 60); ... }
|
我们先解释一下这里的参数,第一个参数是方块,第二个参数是点燃这个方块的几率(有火源的情况下,比如有火在边上),第三个参数是传播给其他方块的几率(火势蔓延)
相比较而言,原木类烧得就慢一点,木板烧得就快一点,树叶烧得就更快一点
别急,我知道你想干什么,Fabric
也给我们提供了相关的API
方块注册
那么现在我们就来注册这些方块吧
注册原木、去皮原木、木头、去皮木头、木板、树叶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| public static final Block ICE_ETHER_LOG = register("ice_ether_log", new PillarBlock(AbstractBlock.Settings.copy(Blocks.OAK_LOG)));
public static final Block ICE_ETHER_WOOD = register("ice_ether_wood", new PillarBlock(AbstractBlock.Settings.copy(Blocks.OAK_WOOD)));
public static final Block STRIPPED_ICE_ETHER_LOG = register("stripped_ice_ether_log", new PillarBlock(AbstractBlock.Settings.copy(Blocks.STRIPPED_OAK_LOG)));
public static final Block STRIPPED_ICE_ETHER_WOOD = register("stripped_ice_ether_wood", new PillarBlock(AbstractBlock.Settings.copy(Blocks.STRIPPED_OAK_WOOD)));
public static final Block ICE_ETHER_PLANKS = register("ice_ether_planks", new Block(AbstractBlock.Settings.copy(Blocks.OAK_PLANKS)));
public static final Block ICE_ETHER_LEAVES = register("ice_ether_leaves", new LeavesBlock(AbstractBlock.Settings.copy(Blocks.OAK_LEAVES)));
|
方便起见,我们这里全部copy
原版的方块,这样就不用一个一个设置了
加入物品栏
1 2 3 4 5 6
| entries.add(ModBlocks.ICE_ETHER_LOG); entries.add(ModBlocks.ICE_ETHER_WOOD); entries.add(ModBlocks.STRIPPED_ICE_ETHER_LOG); entries.add(ModBlocks.STRIPPED_ICE_ETHER_WOOD); entries.add(ModBlocks.ICE_ETHER_PLANKS); entries.add(ModBlocks.ICE_ETHER_LEAVES);
|
这里我们把这些方块加入到物品栏中,这样我们就可以在创造模式中找到这些方块了
注册原木与去皮原木的对应关系
这里我们就用Fabric
的API
来注册这些对应关系
1 2 3
| StrippableBlockRegistry.register(ModBlocks.ICE_ETHER_LOG, ModBlocks.STRIPPED_ICE_ETHER_LOG);
StrippableBlockRegistry.register(ModBlocks.ICE_ETHER_WOOD, ModBlocks.STRIPPED_ICE_ETHER_WOOD);
|
我们将这段语句写在模组主类的onInitialize
方法中,这样就可以在游戏加载时注册这些对应关系了
注册可燃物方块
不过这里我们写之前先做一个区分,我们的可燃物方块和前面讲的燃烧物不是一个东西
燃烧物是可以当作燃料使用的物品或者方块,而可燃物方块是可以被火点燃的方块,这俩还是有点区别的
我们在模组主类的onInitialize
方法中注册这些可燃物方块
1 2 3 4 5 6 7 8 9 10 11
| FlammableBlockRegistry.getDefaultInstance().add(ModBlocks.ICE_ETHER_LOG, 5, 5);
FlammableBlockRegistry.getDefaultInstance().add(ModBlocks.ICE_ETHER_WOOD, 5, 5);
FlammableBlockRegistry.getDefaultInstance().add(ModBlocks.STRIPPED_ICE_ETHER_LOG, 5, 5);
FlammableBlockRegistry.getDefaultInstance().add(ModBlocks.STRIPPED_ICE_ETHER_WOOD, 5, 5);
FlammableBlockRegistry.getDefaultInstance().add(ModBlocks.ICE_ETHER_LEAVES, 30, 60);
FlammableBlockRegistry.getDefaultInstance().add(ModBlocks.ICE_ETHER_PLANKS, 5, 20);
|
这里的参数和原版的一样,这里就不再解释了
数据文件
语言文件
1 2 3 4 5 6
| translationBuilder.add(ModBlocks.ICE_ETHER_LOG, "Ice Ether Log"); translationBuilder.add(ModBlocks.ICE_ETHER_WOOD, "Ice Ether Wood"); translationBuilder.add(ModBlocks.STRIPPED_ICE_ETHER_LOG, "Stripped Ice Ether Log"); translationBuilder.add(ModBlocks.STRIPPED_ICE_ETHER_WOOD, "Stripped Ice Ether Wood"); translationBuilder.add(ModBlocks.ICE_ETHER_PLANKS, "Ice Ether Planks"); translationBuilder.add(ModBlocks.ICE_ETHER_LEAVES, "Ice Ether Leaves");
|
不过,为了让我们的木头可以烧制成木炭,我们还需要一个logs_that_burn
文件
不过,写了这个文件以后,就不用去写燃烧物的方法了,因为在原版中是用logs
这个Tag
来设置原木的燃烧属性的(木头、木板同理),而logs_that_burn
是属于logs
这个Tag
的
1 2 3 4 5
| getOrCreateTagBuilder(BlockTags.LOGS_THAT_BURN) .add(ModBlocks.ICE_ETHER_LOG) .add(ModBlocks.ICE_ETHER_WOOD) .add(ModBlocks.STRIPPED_ICE_ETHER_LOG) .add(ModBlocks.STRIPPED_ICE_ETHER_WOOD);
|
1 2 3 4 5
| getOrCreateTagBuilder(ItemTags.LOGS_THAT_BURN) .add(ModBlocks.ICE_ETHER_LOG.asItem()) .add(ModBlocks.ICE_ETHER_WOOD.asItem()) .add(ModBlocks.STRIPPED_ICE_ETHER_LOG.asItem()) .add(ModBlocks.STRIPPED_ICE_ETHER_WOOD.asItem());
|
两边都写一下,虽然差不多
模型文件
1 2 3 4
| blockStateModelGenerator.registerLog(ModBlocks.ICE_ETHER_LOG).log(ModBlocks.ICE_ETHER_LOG).wood(ModBlocks.ICE_ETHER_WOOD); blockStateModelGenerator.registerLog(ModBlocks.STRIPPED_ICE_ETHER_LOG).log(ModBlocks.STRIPPED_ICE_ETHER_LOG).wood(ModBlocks.STRIPPED_ICE_ETHER_WOOD); blockStateModelGenerator.registerSimpleCubeAll(ModBlocks.ICE_ETHER_PLANKS); blockStateModelGenerator.registerSimpleCubeAll(ModBlocks.ICE_ETHER_LEAVES);
|
这里原木和木头需使用registerLog
方法,这里是对应的原木和木头
而木板和树叶则使用registerSimpleCubeAll
方法,这里是一个简单的六面同材质的方块
另外,贴图文件不要忘记了,随后我们就可以启动我们的游戏了