方块实体渲染器
方块实体渲染器
BlockEntityRenderer
,通常缩写为 BER,用于以静态烘焙模型(JSON、OBJ 等)无法表示的方式渲染方块。例如,这可以用于动态渲染类似箱子的方块的容器内容。方块实体渲染器要求方块具有 BlockEntity
,即使方块不存储任何数据。
要创建 BER,请创建一个继承自 BlockEntityRenderer
的类。它接受一个泛型参数,指定方块的 BlockEntity
类,该类用作 BER 渲染方法中的参数类型。
// 假设存在 MyBlockEntity 作为 BlockEntity 的子类。
public class MyBlockEntityRenderer implements BlockEntityRenderer<MyBlockEntity> {
// 为下面的 lambda 添加构造函数参数。您也可以使用它来获取一些上下文
// 并将其存储在本地字段中,例如实体渲染器分发器(如果需要)。
public MyBlockEntityRenderer(BlockEntityRendererProvider.Context context) {
}
// 此方法每帧调用以渲染方块实体。参数为:
// - blockEntity: 正在渲染的方块实体实例。使用传递给超接口的泛型类型。
// - partialTick: 自上一刻以来经过的时间,以刻的分数表示(0.0 到 1.0)。
// - poseStack: 要渲染到的姿态堆栈。
// - bufferSource: 从中获取顶点缓冲区的缓冲区源。
// - packedLight: 方块实体的光照值。
// - packedOverlay: 方块实体的当前覆盖值,通常为 OverlayTexture.NO_OVERLAY。
@Override
public void render(MyBlockEntity blockEntity, float partialTick, PoseStack stack, MultiBufferSource bufferSource, int packedLight, int packedOverlay) {
// 在此处进行渲染。
}
}
对于给定的 BlockEntityType<?>
,只能存在一个 BER。因此,特定于单个方块实体实例的值应存储在该方块实体实例中,而不是 BER 本身。
创建 BER 后,您还必须将其注册到 EntityRenderersEvent.RegisterRenderers
,这是一个在 Mod 事件总线上触发的事件:
@SubscribeEvent
public static void registerEntityRenderers(EntityRenderersEvent.RegisterRenderers event) {
event.registerBlockEntityRenderer(
// 要为其注册渲染器的方块实体类型。
MyBlockEntities.MY_BLOCK_ENTITY.get(),
// 从 BlockEntityRendererProvider.Context 到 BlockEntityRenderer 的函数。
MyBlockEntityRenderer::new
);
}
如果您在 BER 中不需要 BER 提供者上下文,您也可以删除构造函数:
public class MyBlockEntityRenderer implements BlockEntityRenderer<MyBlockEntity> {
@Override
public void render( /* ... */ ) { /* ... */ }
}
// 在您的事件处理类中
@SubscribeEvent
public static void registerEntityRenderers(EntityRenderersEvent.RegisterRenderers event) {
event.registerBlockEntityRenderer(MyBlockEntities.MY_BLOCK_ENTITY.get(),
// 将上下文传递给空(默认)构造函数调用
context -> new MyBlockEntityRenderer()
);
}
无层级方块实体渲染器
BlockEntityWithoutLevelRenderer
,俗称 BEWLR,是常规 BlockEntityRenderer
的适配器,用于特殊物品渲染(因此称为“无层级”,因为物品没有层级上下文)。它的总体目的相同:在静态模型不足的情况下进行特殊渲染。
要添加 BEWLR,请创建一个扩展 BlockEntityWithoutLevelRenderer
并重写 #renderByItem
的类。它还需要一些额外的构造函数设置:
public class MyBlockEntityWithoutLevelRenderer extends BlockEntityWithoutLevelRenderer {
// 我们需要在构造函数中进行一些样板代码,告诉超类在哪里找到中央方块实体和实体渲染器。
public MyBlockEntityWithoutLevelRenderer() {
super(Minecraft.getInstance().getBlockEntityRenderDispatcher(), Minecraft.getInstance().getEntityModels());
}
@Override
public void renderByItem(ItemStack stack, ItemDisplayContext transform, PoseStack poseStack, MultiBufferSource bufferSource, int packedLight, int packedOverlay) {
// 在此处进行渲染。
}
}
请记住,与 BER 一样,您的 BEWLR 只有一个实例。因此,堆栈特定的属性应存储在堆栈中,而不是 BEWLR 中。
与 BER 不同,我们不直接注册 BEWLR。相反,我们将 IClientItemExtensions
的实例注册到 RegisterClientExtensionsEvent
。IClientItemExtensions
是一个接口,允许我们指定物品上的许多与渲染相关的行为,例如(但不限于)BEWLR。因此,我们的接口实现可能如下所示:
public class MyClientItemExtensions implements IClientItemExtensions {
// 在字段中缓存我们的 BEWLR。
private final MyBlockEntityWithoutLevelRenderer myBEWLR = new MyBlockEntityWithoutLevelRenderer();
// 在此处返回我们的 BEWLR。
@Override
public BlockEntityWithoutLevelRenderer getCustomRenderer() {
return myBEWLR;
}
}
然后,我们可以将 IClientItemExtensions
注册到事件中:
@SubscribeEvent
public static void registerClientExtensions(RegisterClientExtensionsEvent event) {
event.registerItem(
// 我们的 IClientItemExtensions 的唯一实例,因此也是我们的 BEWLR 的唯一实例。
new MyClientItemExtensions(),
// 使用此 BEWLR 的物品的变长参数列表。
MyItems.ITEM_1, MyItems.ITEM_2
);
}
信息:IClientItemExtensions
通常应被视为单例。不要在 RegisterClientExtensionsEvent
之外构造它们!