BlockEntityRenderer
A BlockEntityRenderer
, often abbreviated as BER, is used to render blocks in a way that cannot be represented with a static baked model (JSON, OBJ, others). For example, this could be used to dynamically render container contents of a chest-like block. A block entity renderer requires the block to have a BlockEntity
, even if the block does not store any data otherwise.
To create a BER, create a class that inherits from BlockEntityRenderer
. It takes a generic argument specifying the block's BlockEntity
class, which is used as a parameter type in the BER's render
method.
// Assumes the existence of MyBlockEntity as a subclass of BlockEntity.
public class MyBlockEntityRenderer implements BlockEntityRenderer<MyBlockEntity> {
// Add the constructor parameter for the lambda below. You may also use it to get some context
// to be stored in local fields, such as the entity renderer dispatcher, if needed.
public MyBlockEntityRenderer(BlockEntityRendererProvider.Context context) {
}
// This method is called every frame in order to render the block entity. Parameters are:
// - blockEntity: The block entity instance being rendered. Uses the generic type passed to the super interface.
// - partialTick: The amount of time, in fractions of a tick (0.0 to 1.0), that has passed since the last tick.
// - poseStack: The pose stack to render to.
// - bufferSource: The buffer source to get vertex buffers from.
// - packedLight: The light value of the block entity.
// - packedOverlay: The current overlay value of the block entity, usually OverlayTexture.NO_OVERLAY.
@Override
public void render(MyBlockEntity blockEntity, float partialTick, PoseStack stack, MultiBufferSource bufferSource, int packedLight, int packedOverlay) {
// Do the rendering here.
}
}
Only one BER may exist for a given BlockEntityType<?>
. Therefore, values that are specific to a single block entity instance should be stored in that block entity instance, rather than the BER itself.
When you have created your BER, you must also register it to EntityRenderersEvent.RegisterRenderers
, an event fired on the mod event bus:
@SubscribeEvent
public static void registerEntityRenderers(EntityRenderersEvent.RegisterRenderers event) {
event.registerBlockEntityRenderer(
// The block entity type to register the renderer for.
MyBlockEntities.MY_BLOCK_ENTITY.get(),
// A function of BlockEntityRendererProvider.Context to BlockEntityRenderer.
MyBlockEntityRenderer::new
);
}
In the event that you do not need the BER provider context in your BER, you can also remove the constructor:
public class MyBlockEntityRenderer implements BlockEntityRenderer<MyBlockEntity> {
@Override
public void render( /* ... */ ) { /* ... */ }
}
// In your event handler class
@SubscribeEvent
public static void registerEntityRenderers(EntityRenderersEvent.RegisterRenderers event) {
event.registerBlockEntityRenderer(MyBlockEntities.MY_BLOCK_ENTITY.get(),
// Pass the context to an empty (default) constructor call
context -> new MyBlockEntityRenderer()
);
}
Item Block Rendering
As not all block entities with renderers can be rendered using static models, you can create a special renderer to customize the item rendering process. This is done using SpecialModelRenderer
s. In these cases, both a special model renderer must be created to render the item correctly, and a corresponding registered special block model renderer for scenarios when a block is being rendered as an item (e.g., enderman carrying a block).
Please refer to the client item documentation for more information.