目标: 制作一个拥有独立配方的工作台
- 配方:泥土方块 + 高草丛 = 黏液球 该配方仅能在该工作台使用
tips: 令人反感的是fabric制作组时常给一些好用的方法打上弃用标签,而官方文档又不给出替代方案的使用范例(事实上他们的官方文档一直非常滞后)导致你在编码时有种莫名的恶心感,此时建议大家在编写前给类打上注解@SuppressWarnings("deprecation")
以关闭弃用检查(眼不见心不烦)。
制作方块
这个方块类需要有两个主要部分,一是方块实体,二是鼠标右键后要打开GUI界面。
@SuppressWarnings("deprecation")
public class WorkBlock extends Block implements BlockEntityProvider {
// 方块名称
public static final String NAME = "work_block";
// 方块唯一标识
public static final Identifier ID = new Identifier(ModInfo.MOD_ID, NAME);
// 方块单例实例
public static final Block INSTANCE = new WorkBlock(FabricBlockSettings.create().hardness(0.5f));
// 右键后打开的界面的标题
private static final Text TITLE = Text.translatable("screen.amazing.work_block");
// 方块实体
public static WorkBlockEntity blockEntity;
public WorkBlock(Settings settings) {
super(settings);
}
// 重载右键事件
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
if (world.isClient) {
// 客户端不响应右键事件
return ActionResult.SUCCESS;
} else {
// 在方块位置创建GUI界面(人被水冲远会导致GUI界面自动关闭
NamedScreenHandlerFactory screenHandlerFactory = state.createScreenHandlerFactory(world, pos);
// 屏幕创建后立即打开屏幕
player.openHandledScreen(screenHandlerFactory);
return ActionResult.SUCCESS;
}
}
// 方块实体必须重写的方法
@Nullable
@Override
public BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
blockEntity = new WorkBlockEntity(pos, state);
return blockEntity;
}
// get时使用单例避免创建过多对象,这里即使并发了也无所谓,多出来的会被垃圾回收,只有创建那一瞬间会卡
private WorkBlockEntity getBlockEntity(BlockPos pos, BlockState state) {
if(blockEntity == null){
blockEntity = new WorkBlockEntity(pos, state);
}
return blockEntity;
}
// 这个方法我们自己不会调用,由fabric在state.createScreenHandlerFactory时进行调用
@Nullable
@Override
public NamedScreenHandlerFactory createScreenHandlerFactory(BlockState state, World world, BlockPos pos) {
// 创建一个屏幕工厂,其工厂方法是new一个我们自己的WorkBlockScreenHandler类,这个后面会有代码
return new SimpleNamedScreenHandlerFactory((syncId, inventory, player) ->
new WorkBlockScreenHandler(syncId, player.getInventory(), inventory, ScreenHandlerContext.create(world, pos)), TITLE);
}
// 重写方块被破坏时的方法,在方块实体里面会放入一些东西,如果破坏时不掉落,会吞物品
@Override
public void onBreak(World world, BlockPos pos, BlockState state, PlayerEntity player) {
super.onBreak(world, pos, state, player);
this.getBlockEntity(pos, state).doBreak(world, pos);
}
}
可以看到这里我们还需要去创建方块实体的类和屏幕类,而这些类又会牵扯到更多的新类。我们还有方块材质和合成表数据等json文件需要编写。全部编写完成后仅JAVA代码量约在900行左右。
时间关系先写到这里,后续部分将在本专栏继续更新。