package net.minecraft.client.renderer.blockentity; import com.google.common.collect.ImmutableMap; import com.mojang.blaze3d.vertex.PoseStack; import java.util.Map; import java.util.function.Supplier; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.CrashReport; import net.minecraft.CrashReportCategory; import net.minecraft.ReportedException; import net.minecraft.client.gui.Font; import net.minecraft.client.model.geom.EntityModelSet; import net.minecraft.client.renderer.PlayerSkinRenderCache; import net.minecraft.client.renderer.SubmitNodeCollector; import net.minecraft.client.renderer.block.BlockModelResolver; import net.minecraft.client.renderer.blockentity.state.BlockEntityRenderState; import net.minecraft.client.renderer.entity.EntityRenderDispatcher; import net.minecraft.client.renderer.feature.ModelFeatureRenderer; import net.minecraft.client.renderer.item.ItemModelResolver; import net.minecraft.client.renderer.state.level.CameraRenderState; import net.minecraft.client.resources.model.sprite.SpriteGetter; import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.server.packs.resources.ResourceManagerReloadListener; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.phys.Vec3; import org.jspecify.annotations.Nullable; @Environment(EnvType.CLIENT) public class BlockEntityRenderDispatcher implements ResourceManagerReloadListener { private Map, BlockEntityRenderer> renderers = ImmutableMap.of(); private final Font font; private final Supplier entityModelSet; private Vec3 cameraPos; private final BlockModelResolver blockModelResolver; private final ItemModelResolver itemModelResolver; private final EntityRenderDispatcher entityRenderer; private final SpriteGetter sprites; private final PlayerSkinRenderCache playerSkinRenderCache; public BlockEntityRenderDispatcher( final Font font, final Supplier entityModelSet, final BlockModelResolver blockModelResolver, final ItemModelResolver itemModelResolver, final EntityRenderDispatcher entityRenderer, final SpriteGetter sprites, final PlayerSkinRenderCache playerSkinRenderCache ) { this.blockModelResolver = blockModelResolver; this.itemModelResolver = itemModelResolver; this.entityRenderer = entityRenderer; this.font = font; this.entityModelSet = entityModelSet; this.sprites = sprites; this.playerSkinRenderCache = playerSkinRenderCache; } @Nullable public BlockEntityRenderer getRenderer(final E blockEntity) { return (BlockEntityRenderer)this.renderers.get(blockEntity.getType()); } @Nullable public BlockEntityRenderer getRenderer(final S state) { return (BlockEntityRenderer)this.renderers.get(state.blockEntityType); } public void prepare(final Vec3 cameraPos) { this.cameraPos = cameraPos; } @Nullable public S tryExtractRenderState( final E blockEntity, final float partialTicks, @Nullable final ModelFeatureRenderer.CrumblingOverlay breakProgress, final boolean isGloballyRendered ) { BlockEntityRenderer renderer = this.getRenderer(blockEntity); if (renderer == null) { return null; } else if (!blockEntity.hasLevel() || !blockEntity.getType().isValid(blockEntity.getBlockState())) { return null; } else if (isGloballyRendered != renderer.shouldRenderOffScreen()) { return null; } else if (!renderer.shouldRender(blockEntity, this.cameraPos)) { return null; } else { Vec3 cameraPosition = this.cameraPos; S state = renderer.createRenderState(); renderer.extractRenderState(blockEntity, state, partialTicks, cameraPosition, breakProgress); return state; } } public void submit( final S state, final PoseStack poseStack, final SubmitNodeCollector submitNodeCollector, final CameraRenderState camera ) { BlockEntityRenderer renderer = this.getRenderer(state); if (renderer != null) { try { renderer.submit(state, poseStack, submitNodeCollector, camera); } catch (Throwable var9) { CrashReport report = CrashReport.forThrowable(var9, "Rendering Block Entity"); CrashReportCategory category = report.addCategory("Block Entity Details"); state.fillCrashReportCategory(category); throw new ReportedException(report); } } } @Override public void onResourceManagerReload(final ResourceManager resourceManager) { BlockEntityRendererProvider.Context context = new BlockEntityRendererProvider.Context( this, this.blockModelResolver, this.itemModelResolver, this.entityRenderer, (EntityModelSet)this.entityModelSet.get(), this.font, this.sprites, this.playerSkinRenderCache ); this.renderers = BlockEntityRenderers.createEntityRenderers(context); } }