NeoForge-1.20.4Mod开发教程之自定义方块模型和非实心方块

本篇教程参考为Flandre芙兰的NeoForge1.20.4Mod开发的视频,这篇教程是我边学边总结的,与其说是教程更像我的学习笔记,如有不清楚的地方,大家可以在评论区提问。在我力所能及的范围内,我都会解答的。

创建RubyFrame类

public class RubyFrame extends Block implements SimpleWaterloggedBlock {
     public RubyFrame() {
         super(Properties.ofFullCopy(Blocks.STONE).strength(5).noOcclusion());//.noOcclusion():渲染这个方块遮挡的那些面。不开启的效果见下图
         this.registerDefaultState(this.stateDefinition.any().setValue(BlockStateProperties.WATERLOGGED, false));//注册默认的方块状态,之前的Lamp中也写过
    }
     public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED;//表示方块是否含水
     public static final VoxelShape SHAPE1 = Block.box(0,0,0,16,2,16);//碰撞箱,模型起始坐标和结束坐标,这两是对角
     public static final VoxelShape SHAPE2 = Block.box(0,14,0,16,16,16);
     public static final VoxelShape SHAPE3 = Block.box(0,2,0,2,14,2);
     public static final VoxelShape SHAPE4 = Block.box(0,2,16,2,14,16);
     public static final VoxelShape SHAPE5 = Block.box(14,2,0,16,14,2);
     public static final VoxelShape SHAPE6 = Block.box(14,2,14,16,14,16);
     public static final VoxelShape ALL_SHAPE = Shapes.or(SHAPE1, SHAPE2, SHAPE3, SHAPE4, SHAPE5, SHAPE6);
 ​
     @Override
     public  VoxelShape getShape( BlockState state,  BlockGetter reader,  BlockPos pos,  CollisionContext collisionContext) {//返回方块的碰撞箱
         return ALL_SHAPE;
    }
 ​
     @Override
     protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {//将WATERLOGGED属性添加到方块的状态中,表示该方块是否包含水
         builder.add(WATERLOGGED);
    }
 ​
     @Override
     public BlockState getStateForPlacement(BlockPlaceContext ctx) {//检查放置位置的液体状态,如果位置有水,它会将WATERLOGGED设置为true,表示该方块被水浸
         BlockPos blockpos = ctx.getClickedPos();
         FluidState fluidstate = ctx.getLevel().getFluidState(blockpos);
         return this.defaultBlockState().setValue(WATERLOGGED, fluidstate.getType() == Fluids.WATER);
    }
         
     @Override
     public BlockState updateShape(BlockState state,//用于更新方块状态时处理与水相关的行为
                                   Direction facing,
                                   BlockState facingState,
                                   LevelAccessor level,
                                   BlockPos currentPos,
                                   BlockPos facingPos) {
         if (state.getValue(WATERLOGGED)) {
             level.scheduleTick(currentPos, Fluids.WATER, Fluids.WATER.getTickDelay(level));
        }
         return super.updateShape(state, facing, facingState, level, currentPos, facingPos);
    }
     
     @Override
     public  FluidState getFluidState(BlockState state) {//获取方块的液体状态,如果方块的WATERLOGGED属性为 true,则返回水源(Fluids.WATER.getSource(false)),否则,调用父类的方法返回默认的液体状态
         return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state);
    }
 ​
     protected boolean isPathfindable(BlockState state,PathComputationType type) {//用于确定方块是否可以作为路径的一部分
         return switch (type) {
             case LAND -> false;//如果是陆地,返回 false,表示方块无法作为路径,即生物不会踩上去
             case WATER -> state.getFluidState().is(FluidTags.WATER);//如果是水路径,检查方块的液体状态是否是水
             case AIR -> false;
             default -> false;
        };
    }
 ​
 }

 

7e6ae45a5020260206184857

updateShapegetFluidState具体在游戏中的作用我也不清楚,把这两方法删了不影响方块在游戏里的任何方面

最后不要忘记注册方块和物品之类的操作

 

材质和模型

模型通过BlockBench这个软件来建模并导出json和png

{
  "format_version": "1.9.0",
  "credit": "Made with Blockbench",
  "texture_size": [64, 64],
  "textures": {
  "0": "examplemod:block/ruby_frame",//这两个路径很重要,写错了就是黑紫块
  "particle": "examplemod:block/ruby_frame"
  },
  ...省略...

数据生成ModBlockStateProvider

这个方法用于给提供了模型json的方块写blockstates和blockitem的json

public void addwithHaveModel(Block block,String name) {
         var model_path= models().getExistingFile(new ResourceLocation(ExampleMod.MODID,name));
         var model=new ConfiguredModel(model_path);
         getVariantBuilder(block).partialState().setModels(model);
         simpleBlockItem(block,model_path);
    }

最后在这里添加就行了

@Override
     protected void registerStatesAndModels() {
         this.simpleBlock(ModBlocks.RUBY_BLOCK.get(),cubeAll(ModBlocks.RUBY_BLOCK.get()));
         this.simpleBlockItem(ModBlocks.RUBY_BLOCK.get(),cubeAll(ModBlocks.RUBY_BLOCK.get()));
         this.propertyBlock(ModBlocks.LAMP_BLOCK.get());
         this.addwithHaveModel(ModBlocks.RUBY_FRAME.get(),"ruby_frame");
    }
© 版权声明
THE END
喜欢就支持一下吧
点赞6赞赏 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容