GeckoLib 1.20 Fabric 长线教程计划
本篇教程的视频
(待发布)
本篇教程的源代码
(待发布)
本篇教程目标
为模组添加依赖于GeckoLib的方块和物品
介绍
GeckoLib,也就是壁虎库,我们熟知的YSM模组也是用了GeckoLib作为核心开发的
简单来说,GeckoLib是一个用于创建模型和动画的库,可以让开发者在Java版中使用基岩版的模型和动画,其仓库参见:GeckoLib
在我们需要制作一些高精度模型或者复杂动画时,GeckoLib是一个不错的选择
我这里所说的高精度模型,也就是没有那22.5度旋转限制和单轴旋转限制的模型;不过呢,这只是对于我们这个系列的1.20.1而言的
这里我多说几句,在后面的版本中,从1.21.6开始,原版的模型不再受22.5度的旋转限制了;
从1.21.11开始,也不再受单轴旋转限制了,所以在高版本中,原版的模型就可以支持较高精度了(所以一步到位,可以直接去尝试26.1的开发)
那么这篇教程的话,也是作为我们方块实体系列的前置,因为GeckoLib的方块模型加载方式,其实就是用方块实体来实现的
当然这篇教程只是让我们的模组加载GeckoLib的模型,方块实体的那些真正的处理逻辑我们到后面再说
添加依赖
那么GecokoLib作为我们模组的依赖,首先我们得添加它
在build.gradle中添加依赖
1 | repositories { |
这里的geckolib_version需要我们到gradle.properties中添加版本信息,版本可以在模组站上找到,可以找一个下载量高的版本(因为用的人多)
1 | geckolib_version=4.7.1.2 |
而后就是重载Gradle项目,另外再运行一下genSources
关于建模和动画
安装插件
GeckoLib相关的模型和动画自然还是用我们的老朋友Blockbench来完成,但需要安装插件GeckoLib Models & Animations
新建项目
然后在我们的开始界面就会有一个GeckoLib Animated Model选项,点击创建新模型
而后会弹出一个小窗口,Model Type可以直接选择Item,因为会多一个显示调整标签页,方便调整它在物品栏、手持视角的显示,这个类型不会影响我们最终的模型类型
至于实体,我们以后有机会再讲吧,现阶段的教程没有生物实体的教程计划
导出模型
在我们做好模型后,下一步就是导出了,导出的内容包括模型文件本身、材质文件、显示文件、动画文件(如果有)
文件->导出->Export GeckoLib Model,这是导出模型文件,我们会得到一个.geo.json文件;文件->导出->Export GeckoLib Display Settings,这是导出显示文件,也就是我们在显示调整中调整好的显示信息,我们会得到一个.json文件;文件->导出->Export GeckoLib Animations,这是导出动画文件,我们会得到一个.animation.json文件
贴图也记得保存
另外,强烈建议将项目本身(.bbmodel)也进行保存,因为导出的.geo.json文件虽然可以用Blockbench打开,但会缺失一些东西,不方便我们再编辑
导出这些文件之后,将这些文件放置到我们项目assets目录下的相应位置,具体位置如下:
assets/<modid>/geo下放置.geo.json文件assets/<modid>/textures/block(如果是物品则放item)下放置.png贴图assets/<modid>/animations下放置.animation.json文件assets/<modid>/models/block(如果是物品则放item)下放置.json文件
鉴于本教程的视频教程尚未推出,这里先放一个临时仓库,大家如果需要文件,可自取:
Tutorial Mod Re Template 1.20.1-fab
编写代码
那么接下来我们就开始写代码,鉴于方块和物品的流程相似,我们这里只跑一次添加方块的流程
总的来说,我们的整个流程是这样的:
- 创建方块类(Block);
- 注册方块(ModBlocks);
- 创建方块实体类(BlockEntity);
- 注册方块实体(ModBlockEntities);
- 创建物品类(Item);
- 注册物品(ModItems);
- 创建方块模型 & 物品模型类(Model);
- 创建方块渲染器 & 物品渲染器类(Renderer),并完善物品类;
- 客户端类方块渲染器注册(ClientModInitializer);
- 其他数据文件(DataGen);
方块的整体流程就这样,内容比较多,但也不是很复杂
如果是物品的话,其实从第5步开始就好了,和方块的流程一样
主类初始化
不过在正式开始之前,我们需要向主类添加一行代码
1 | GeckoLib.initialize(); |
没有它的话,GeckoLib相关的内容就无法完成初始化,我们的模型会无法正确加载
创建方块类
这里我们新建一个PortableOriginiumRigBlock,继承自BlockWithEntity
1 | public class PortableOriginiumRigBlock extends BlockWithEntity { |
创建构造函数,并重写createBlockEntity方法
显然,这里的便携源石矿机是从终末地工业模组中拿过来的,后续我们将在它的基础上进行我们的方块实体系列
等我们写了方块实体之后,再来完善createBlockEntity方法的返回值
注册方块
接下来到ModBlocks中添加方块
1 | public static final Block PORTABLE_ORIGINIUM_RIG = registerBlocksWithoutItem("portable_originium_rig", |
这里我们再加一个方法,因为在这里我们不需要注册物品,物品等会单独去注册
然后使用registerBlocksWithoutItem方法注册方块,里面内容跟之前一样,这里我就不再赘述
创建方块实体类
接下来我们创建方块实体类PortableOriginiumRigBlockEntity,继承BlockEnity,实现GeoBlockEntity接口
1 | public class PortableOriginiumRigBlockEntity extends BlockEntity implements GeoBlockEntity { |
创建构造函数,并重写相关方法
然后我们来创建一些东西
1 | private final AnimatableInstanceCache cache = GeckoLibUtil.createInstanceCache(this); |
AnimatableInstanceCache是GeckoLib提供的一个缓存类,用于缓存动画实例(应该是为了降低性能损耗的),这里我们使用GeckoLibUtil.createInstanceCache(this)创建一个缓存实例,并返回
registerControllers方法中,我们创建了一个AnimationController,并添加了一个AnimationController,用于控制动画播放,这里指向working动画(在本篇教程提供的动画文件中,其实还有一个idle动画,我们留到后面方块实体的教程再说吧)
注册方块实体
我们到ModBlockEntities类中,添加以下内容(这个类我们之前写过了,这里就不再赘述了)
1 | public static final BlockEntityType<PortableOriginiumRigBlockEntity> PORTABLE_ORIGINIUM_RIG = create("portable_originium_rig", |
当然现在还会报错,我们还需要改写一些方块实体类的构造函数
1 | public PortableOriginiumRigBlockEntity(BlockPos pos, BlockState state) { |
这样就好了
另外,我们还需要修改方块类中的createBlockEntity方法
1 |
|
创建物品类
这里我们新建一个PortableOriginiumRigItem,继承BlockItem,并实现GeoItem接口
1 | public class PortableOriginiumRigItem extends BlockItem implements GeoItem { |
创建构造函数,并重写相关方法
这里我们需要向构造函数中添加一行语句
1 | public PortableOriginiumRigItem(Block block, Settings settings) { |
这里我们调用了SingletonGeoAnimatable.registerSyncedAnimatable(this)方法,用于注册同步动画
然后创建cache和renderProvider,并重写相关方法
1 | private final AnimatableInstanceCache cache = new SingletonAnimatableInstanceCache(this); |
createRenderer方法等我们写完渲染器类再来完善
注册物品
我们在ModItems类中添加以下内容
1 | public static final Item PORTABLE_ORIGINIUM_RIG_ITEM = registerItems("portable_originium_rig", |
另外不要忘记将其添加到物品栏
1 | entries.add(ModItems.PORTABLE_ORIGINIUM_RIG_ITEM); |
创建方块模型 & 物品模型类
接下来我们要创建两个类,一个是PortableOriginiumModel,一个是PortableOriginiumItemModel,都继承GeoModel,但泛型不同
1 | public class PortableOriginiumModel extends GeoModel<PortableOriginiumRigBlockEntity> { |
重写getModelResource、getTextureResource、getAnimationResource方法,其实就是告诉程序模型、纹理和动画文件的位置
1 | public class PortableOriginiumItemModel extends GeoModel<PortableOriginiumRigItem> { |
物品模型类也一样,泛型是PortableOriginiumRigItem
创建方块 & 物品渲染器类
有了模型类之后,渲染器就可以渲染了,接下来我们先写方块的渲染器类,创建一个PortableOriginiumRigRenderer类,继承GeoBlockRenderer,泛型是PortableOriginiumRigBlockEntity
1 | public class PortableOriginiumRigRenderer extends GeoBlockRenderer<PortableOriginiumRigBlockEntity> { |
构造函数中传入模型类,记得将构造函数的参数改为BlockEntityRendererFactory.Context context
方块的渲染器类还需要在客户端类中进行注册
1 | BlockEntityRendererFactories.register(ModBlockEntities.PORTABLE_ORIGINIUM_RIG, PortableOriginiumRigRenderer::new); |
接下来我们写物品的渲染器类,创建一个PortableOriginiumRigItemRenderer类,继承GeoItemRenderer,泛型是PortableOriginiumRigItem
1 | public class PortableOriginiumRigItemRenderer extends GeoItemRenderer<PortableOriginiumRigItem> { |
构造函数不需要参数,然后传入模型类
然后,在物品类的createRenderer方法我们就可以写了
1 |
|
这里我们传入了一个RenderProvider,然后创建了一个PortableOriginiumRigItemRenderer对象,并返回给BuiltinModelItemRenderer
那么到这里为止,代码部分就这样结束了,接下来还有一些数据文件
这整套流程确实有点多,稍微有点复杂,不过习惯就好了
数据文件
那么数据文件我们还是交给数据生成去跑
语言文件
1 | translationBuilder.add(ModItems.PORTABLE_ORIGINIUM_RIG_ITEM, "Portable Originium Rig"); |
战利品列表
1 | addDrop(ModBlocks.PORTABLE_ORIGINIUM_RIG); |
模型文件
1 | blockStateModelGenerator.registerSimpleState(ModBlocks.PORTABLE_ORIGINIUM_RIG); |
在此之后,我们就可以跑数据生成了,然后运行游戏进行测试









