本篇教程的视频
本篇教程的源代码
GitHub地址:
自定义方块类
告示牌是属于方块实体了,如果你挖过相关的源代码,你就会发现它在方块实体注册时,它的方块实体类型注册是硬编码的
不过,Forge这里提供了额外的方法,我们可以通过它提供的方法去重写方块实体的注册类型
当然,我们需要去创建自己的方块实体和方块
首先先写四个方块类,各自继承原版的四种不同类型的告示牌,并重写newBlockEntity方法,相应的方块实体我们后面再写
ModStandingSignBlock
1 2 3 4 5 6 7 8 9 10
| public class ModStandingSignBlock extends StandingSignBlock { public ModStandingSignBlock(Properties pProperties, WoodType pType) { super(pProperties, pType); }
@Override public BlockEntity newBlockEntity(BlockPos pPos, BlockState pState) { return new ModSignBlockEntity(pPos, pState); } }
|
ModHangingSignBlock
1 2 3 4 5 6 7 8 9 10
| public class ModHangingSignBlock extends CeilingHangingSignBlock { public ModHangingSignBlock(Properties pProperties, WoodType pType) { super(pProperties, pType); }
@Override public BlockEntity newBlockEntity(BlockPos pPos, BlockState pState) { return new ModHangingSignBlockEntity(pPos, pState); } }
|
ModWallSignBlock
1 2 3 4 5 6 7 8 9 10
| public class ModWallSignBlock extends WallSignBlock { public ModWallSignBlock(Properties pProperties, WoodType pType) { super(pProperties, pType); }
@Override public BlockEntity newBlockEntity(BlockPos pPos, BlockState pState) { return new ModSignBlockEntity(pPos, pState); } }
|
ModWallHangingSignBlock
1 2 3 4 5 6 7 8 9 10
| public class ModWallHangingSignBlock extends WallHangingSignBlock { public ModWallHangingSignBlock(Properties pProperties, WoodType pType) { super(pProperties, pType); }
@Override public BlockEntity newBlockEntity(BlockPos pPos, BlockState pState) { return new ModHangingSignBlockEntity(pPos, pState); } }
|
虽然说是4个方块类,实际上对应的是两个类型的方块,一个是普通告示牌,一个是悬挂告示牌,只不过它们各有两个状态
注册方块
注册方块之前我们先写一个WoodType,因为它关乎我们告示牌的材质
1
| public static final WoodType ICE_ETHER_WOOD_TYPE = WoodType.register(new WoodType(TutorialMod.MOD_ID + ":ice_ether", BlockSetType.OAK));
|
并在主类的onClientSetup方法中注册这个WoodType
1
| Sheets.addWoodType(ModBlocks.ICE_ETHER_WOOD_TYPE);
|
接下来,我们写四个方块
1 2 3 4 5 6 7 8 9 10 11
| public static final RegistryObject<Block> ICE_ETHER_SIGN = BLOCKS.register("ice_ether_sign", () -> new ModStandingSignBlock(BlockBehaviour.Properties.copy(Blocks.OAK_SIGN), ICE_ETHER_WOOD_TYPE)); public static final RegistryObject<Block> ICE_ETHER_WALL_SIGN = BLOCKS.register("ice_ether_wall_sign", () -> new ModWallSignBlock(BlockBehaviour.Properties.copy(Blocks.OAK_WALL_SIGN), ICE_ETHER_WOOD_TYPE));
public static final RegistryObject<Block> ICE_ETHER_HANGING_SIGN = BLOCKS.register("ice_ether_hanging_sign", () -> new ModHangingSignBlock(BlockBehaviour.Properties.copy(Blocks.OAK_HANGING_SIGN), ICE_ETHER_WOOD_TYPE));
public static final RegistryObject<Block> ICE_ETHER_WALL_HANGING_SIGN = BLOCKS.register("ice_ether_wall_hanging_sign", () -> new ModWallHangingSignBlock(BlockBehaviour.Properties.copy(Blocks.OAK_WALL_HANGING_SIGN), ICE_ETHER_WOOD_TYPE));
|
这里我们先将方块注册了,当然注意,这里是直接调用BLOCKS.register方法的,物品的我们额外写
注册物品
1 2 3 4 5 6
| public static final RegistryObject<Item> ICE_ETHER_SIGN = ITEMS.register("ice_ether_sign", () -> new SignItem(new Item.Properties().stacksTo(16), ModBlocks.ICE_ETHER_SIGN.get(), ModBlocks.ICE_ETHER_WALL_SIGN.get()));
public static final RegistryObject<Item> ICE_ETHER_HANGING_SIGN = ITEMS.register("ice_ether_hanging_sign", () -> new HangingSignItem(ModBlocks.ICE_ETHER_HANGING_SIGN.get(), ModBlocks.ICE_ETHER_WALL_HANGING_SIGN.get(), new Item.Properties().stacksTo(16)));
|
像原版一样,我们可以将它的最大堆叠上限设置为16
不要忘记将其添加到物品栏
1 2
| pOutput.accept(ModItems.ICE_ETHER_SIGN.get()); pOutput.accept(ModItems.ICE_ETHER_HANGING_SIGN.get());
|
自定义方块实体类
ModSignBlockEntity
1 2 3 4 5 6 7 8 9 10
| public class ModSignBlockEntity extends SignBlockEntity { public ModSignBlockEntity(BlockPos pPos, BlockState pBlockState) { super(pPos, pBlockState); }
@Override public BlockEntityType<?> getType() { } }
|
重写getType()方法,先空着
ModHangingSignBlockEntity
1 2 3 4 5 6 7 8 9 10
| public class ModHangingSignBlockEntity extends SignBlockEntity { public ModHangingSignBlockEntity(BlockPos pPos, BlockState pBlockState) { super(pPos, pBlockState); }
@Override public BlockEntityType<?> getType() { } }
|
同样重写getType()方法,先空着
ModBlockEntities
这个类用于方块实体的注册,不过,方块实体的教程还在后面,这里我们只是简单接触一下
1 2 3 4 5 6 7 8
| public class ModBlockEntities { public static final DeferredRegister<BlockEntityType<?>> BLOCK_ENTITIES = DeferredRegister.create(ForgeRegistries.BLOCK_ENTITY_TYPES, TutorialMod.MOD_ID); public static void register(IEventBus bus) { BLOCK_ENTITIES.register(bus); } }
|
先把两个常规的东西写上,并在主类调用register方法
1
| ModBlockEntities.register(modEventBus);
|
然后是方块实体的注册
1 2 3 4 5 6 7 8 9
| public static final RegistryObject<BlockEntityType<ModSignBlockEntity>> MOD_SIGN = BLOCK_ENTITIES.register("mod_sign", () -> BlockEntityType.Builder.of(ModSignBlockEntity::new, ModBlocks.ICE_ETHER_SIGN.get(), ModBlocks.ICE_ETHER_WALL_SIGN.get()).build(null));
public static final RegistryObject<BlockEntityType<ModHangingSignBlockEntity>> MOD_HANGING_SIGN = BLOCK_ENTITIES.register("mod_hanging_sign", () -> BlockEntityType.Builder.of(ModHangingSignBlockEntity::new, ModBlocks.ICE_ETHER_HANGING_SIGN.get(), ModBlocks.ICE_ETHER_WALL_HANGING_SIGN.get()).build(null));
|
这里的注册调用的是BlockEntityType.Builder.of,未来讲到方块实体我们会经常用到
然后我们可以将前面两个方块实体的方法给补全了,顺便再改一下构造函数
ModSignBlockEntity
1 2 3 4 5 6 7 8 9 10
| public class ModSignBlockEntity extends SignBlockEntity { public ModSignBlockEntity(BlockPos pPos, BlockState pBlockState) { super(ModBlockEntities.MOD_SIGN.get(), pPos, pBlockState); }
@Override public BlockEntityType<?> getType() { return ModBlockEntities.MOD_SIGN.get(); } }
|
ModHangingSignBlockEntity
1 2 3 4 5 6 7 8 9 10
| public class ModHangingSignBlockEntity extends SignBlockEntity { public ModHangingSignBlockEntity(BlockPos pPos, BlockState pBlockState) { super(ModBlockEntities.MOD_HANGING_SIGN.get(), pPos, pBlockState); }
@Override public BlockEntityType<?> getType() { return ModBlockEntities.MOD_HANGING_SIGN.get(); } }
|
方块实体渲染器注册
在ClientModEvents中的registerRenderers方法中添加以下内容
1 2
| event.registerBlockEntityRenderer(ModBlockEntities.MOD_SIGN.get(), SignRenderer::new); event.registerBlockEntityRenderer(ModBlockEntities.MOD_HANGING_SIGN.get(), HangingSignRenderer::new);
|
我们还需要针对方块实体的渲染器进行注册,不然游戏不知道如何渲染
数据文件
战利品列表
1 2 3 4 5 6 7 8
| add(ModBlocks.ICE_ETHER_SIGN.get(), createSingleItemTable(ModItems.ICE_ETHER_SIGN.get())); add(ModBlocks.ICE_ETHER_WALL_SIGN.get(), createSingleItemTable(ModItems.ICE_ETHER_SIGN.get())); add(ModBlocks.ICE_ETHER_HANGING_SIGN.get(), createSingleItemTable(ModItems.ICE_ETHER_HANGING_SIGN.get())); add(ModBlocks.ICE_ETHER_WALL_HANGING_SIGN.get(), createSingleItemTable(ModItems.ICE_ETHER_HANGING_SIGN.get()));
|
语言文件
1 2
| add(ModItems.ICE_ETHER_SIGN.get(), "Ice Ether Sign"); add(ModItems.ICE_ETHER_HANGING_SIGN.get(), "Ice Ether Hanging Sign");
|
模型文件
物品的模型文件只要写悬挂告示牌的模型文件即可
1 2 3 4 5 6 7 8 9 10 11
| signBlock(((StandingSignBlock) ModBlocks.ICE_ETHER_SIGN.get()), ((WallSignBlock) ModBlocks.ICE_ETHER_WALL_SIGN.get()), blockTexture(ModBlocks.ICE_ETHER_PLANKS.get()));
hangingSignBlock(ModBlocks.ICE_ETHER_HANGING_SIGN.get(), ModBlocks.ICE_ETHER_WALL_HANGING_SIGN.get(), blockTexture(ModBlocks.ICE_ETHER_PLANKS.get()));
public void hangingSignBlock(Block signBlock, Block wallSignBlock, ResourceLocation texture) { ModelFile sign = models().sign(ForgeRegistries.BLOCKS.getKey(signBlock).getPath(), texture); simpleBlock(signBlock, sign); simpleBlock(wallSignBlock, sign); }
|
悬挂告示牌的生成方法我们是自定义的
接下来还有物品模型
1 2
| basicItem(ModItems.ICE_ETHER_SIGN.get()); basicItem(ModItems.ICE_ETHER_HANGING_SIGN.get());
|
材质
我们需要准备两个方块的展开图材质,两个物品材质
其中一般告示牌的展开图需要放置在textures/entity/signs下,悬挂告示牌的展开图需要放置在textures/entity/signs/hanging下
测试
跑好数据生成,我们就可以启动游戏进行测试了