方块实体渲染器

方块实体渲染器

BlockEntityRenderer 通常简称 BER,用于渲染无法用 JSON、OBJ 等静态烘焙模型表示的方块。例如,它可以动态渲染类似箱子的方块内存放的物品。使用方块实体渲染器要求方块具有 BlockEntity,即使该方块本身不需要存储数据也一样。

BER 直接实现 BlockEntityRenderer,提交需要渲染的特征:

// The generic type in the superinterface should be set to what block entity
// you are trying to render, along with its extracted render state. More on this below.
public class MyBlockEntityRenderer implements BlockEntityRenderer<MyBlockEntity, MyBlockEntityRenderState> {

    public MyBlockEntityRenderer(BlockEntityRendererProvider.Context context) {
        // Get whatever is necessary from the context
    }

    // Tell the renderer how to create a new render state.
    @Override
    public MyBlockEntityRenderState createRenderState() {
        return new MyBlockEntityRenderState();
    }

    // Update the render state by copying the needed values from the passed block entity
    // to the passed render state.
    // The block entity and render state are the generic types passed to the renderer
    @Override
    public void extractRenderState(MyBlockEntity blockEntity, MyBlockEntityRenderState renderState, float partialTick, Vec3 cameraPos, @Nullable ModelFeatureRenderer.CrumblingOverlay crumblingOverlay) {
        // Always call super or `BlockEntityRenderState#extractBase`
        super.extractRenderState(blockEntity, renderState, partialTick, cameraPos, crumblingOverlay);

        // Extract and store any additional values in the state here.
        renderState.value = blockEntity.getValue();
    }

    // Actually submit the features of the block entity to render.
    // The first parameter matches the render state's generic type.
    @Override
    public void submit(MyBlockEntityRenderState renderState, PoseStack poseStack, SubmitNodeCollector collector, CameraRenderState cameraState) {
        // Submit using the collector here.
    }
}

创建 BER 后,还需要注册它,并将其关联到对应的方块实体。可以在 EntityRenderersEvent.RegisterRenderers 中完成:

@SubscribeEvent // on the mod event bus only on the physical client
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
    );
}

提示

如果 BER 不需要使用提供者上下文,也可以移除构造方法:

public class MyBlockEntityRenderer implements BlockEntityRenderer<MyBlockEntity, MyBlockEntityRenderState> {
    
    // ...
}

// In some event handler class
@SubscribeEvent // on the mod event bus only on the physical client
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()
    );
}

方块实体渲染状态

如前面的示例所示,方块实体渲染状态用于从实际方块实体中提取渲染所需的值。它本质上是继承 BlockEntityRenderState 的可变数据存储对象:

public class MyBlockEntityRenderState extends BlockEntityRenderState {
    public boolean value;
}

然后在 BlockEntityRenderer#extractRenderState 中,从 BlockEntity 子类提取数据,填充这些字段。

方块的物品渲染

并非所有带渲染器的方块实体都能用静态物品模型表示,因此可以创建特殊渲染器,更灵活地控制渲染过程。这通过 SpecialModelRenderer 实现。此时,既需要创建特殊模型渲染器以提交所需的特征,也要注册相应的特殊方块模型渲染器,用于直接提交方块本身而非其物品形态的场景,例如末影人搬运方块时。

更多信息请参阅客户端物品文档。


来源: NeoForged/Documentation(26.1)。中文翻译依据提交 4a680cdd4d15。