The BlockEntity Class
In addition to a Block class, we need a BlockEntity class to so that custom rendering can be performed for the block.
This tutorial is specifically for GeckoLib implementation. For information on general-modding block features, seek a tutorial or community support.
Creating the class
Green highlights show added or modified lines of code for each step.
First, we create the base BlockEntity class:
public class ExampleBlockEntity extends BlockEntity {
}
Then, we will implement the GeoBlockEntity interface and override the getAnimatableInstanceCache and registerControllers methods:
public class ExampleBlockEntity extends BlockEntity implements GeoBlockEntity {
@Override
public void registerControllers(final AnimatableManager.ControllerRegistrar controllers) {
// We can fill this in later
}
@Override
public AnimatableInstanceCache getAnimatableInstanceCache() {
return null;
}
}
Next, let's instantiate an AnimatableInstanceCache in a final field at the top of our class, and return it in getAnimatableInstanceCache:
public class ExampleBlockEntity extends BlockEntity implements GeoBlockEntity {
private final AnimatableInstanceCache geoCache = GeckoLibUtil.createInstanceCache(this);
@Override
public void registerControllers(final AnimatableManager.ControllerRegistrar controllers) {
// We can fill this in later
}
@Override
public AnimatableInstanceCache getAnimatableInstanceCache() {
return this.geoCache;
}
}
- Fabric
- Forge
- NeoForge
Then we add the constructor, referencing our BlockEntity type (which we will register later):
public class ExampleBlockEntity extends BlockEntity {
private final AnimatableInstanceCache geoCache = GeckoLibUtil.createInstanceCache(this);
public ExampleBlockEntity(BlockPos pos, BlockState state) {
super(BlockEntityRegistry.EXAMPLE_BLOCK_ENTITY, pos, state);
}
@Override
public void registerControllers(final AnimatableManager.ControllerRegistrar controllers) {
// We can fill this in later
}
@Override
public AnimatableInstanceCache getAnimatableInstanceCache() {
return this.geoCache;
}
}
Then we add the constructor, referencing our BlockEntity type (which we will register later):
public class ExampleBlockEntity extends BlockEntity {
private final AnimatableInstanceCache geoCache = GeckoLibUtil.createInstanceCache(this);
public ExampleBlockEntity(BlockPos pos, BlockState state) {
super(BlockEntityRegistry.EXAMPLE_BLOCK_ENTITY.get(), pos, state);
}
@Override
public void registerControllers(final AnimatableManager.ControllerRegistrar controllers) {
// We can fill this in later
}
@Override
public AnimatableInstanceCache getAnimatableInstanceCache() {
return this.geoCache;
}
}
Then we add the constructor, referencing our BlockEntity type (which we will register later):
public class ExampleBlockEntity extends BlockEntity {
private final AnimatableInstanceCache geoCache = GeckoLibUtil.createInstanceCache(this);
public ExampleBlockEntity(BlockPos pos, BlockState state) {
super(BlockEntityRegistry.EXAMPLE_BLOCK_ENTITY.get(), pos, state);
}
@Override
public void registerControllers(final AnimatableManager.ControllerRegistrar controllers) {
// We can fill this in later
}
@Override
public AnimatableInstanceCache getAnimatableInstanceCache() {
return this.geoCache;
}
}
And you're done!
For information on adding animation controllers, see the Animation Controllers page.