package net.minecraft.client.renderer.entity; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.math.Axis; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.MapRenderer; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.block.BlockRenderDispatcher; import net.minecraft.client.renderer.entity.state.ItemFrameRenderState; import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.client.renderer.texture.TextureAtlas; import net.minecraft.client.resources.model.BlockStateModelLoader; import net.minecraft.client.resources.model.ModelManager; import net.minecraft.client.resources.model.ModelResourceLocation; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.component.DataComponents; import net.minecraft.network.chat.Component; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.decoration.ItemFrame; import net.minecraft.world.item.ItemDisplayContext; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.saveddata.maps.MapId; import net.minecraft.world.level.saveddata.maps.MapItemSavedData; import net.minecraft.world.phys.Vec3; @Environment(EnvType.CLIENT) public class ItemFrameRenderer extends EntityRenderer { public static final int GLOW_FRAME_BRIGHTNESS = 5; public static final int BRIGHT_MAP_LIGHT_ADJUSTMENT = 30; private final ItemRenderer itemRenderer; private final MapRenderer mapRenderer; private final BlockRenderDispatcher blockRenderer; public ItemFrameRenderer(EntityRendererProvider.Context context) { super(context); this.itemRenderer = context.getItemRenderer(); this.mapRenderer = context.getMapRenderer(); this.blockRenderer = context.getBlockRenderDispatcher(); } protected int getBlockLightLevel(T entity, BlockPos pos) { return entity.getType() == EntityType.GLOW_ITEM_FRAME ? Math.max(5, super.getBlockLightLevel(entity, pos)) : super.getBlockLightLevel(entity, pos); } public void render(ItemFrameRenderState renderState, PoseStack poseStack, MultiBufferSource bufferSource, int packedLight) { super.render(renderState, poseStack, bufferSource, packedLight); poseStack.pushPose(); Direction direction = renderState.direction; Vec3 vec3 = this.getRenderOffset(renderState); poseStack.translate(-vec3.x(), -vec3.y(), -vec3.z()); double d = 0.46875; poseStack.translate(direction.getStepX() * 0.46875, direction.getStepY() * 0.46875, direction.getStepZ() * 0.46875); float f; float g; if (direction.getAxis().isHorizontal()) { f = 0.0F; g = 180.0F - direction.toYRot(); } else { f = -90 * direction.getAxisDirection().getStep(); g = 180.0F; } poseStack.mulPose(Axis.XP.rotationDegrees(f)); poseStack.mulPose(Axis.YP.rotationDegrees(g)); ItemStack itemStack = renderState.itemStack; if (!renderState.isInvisible) { ModelManager modelManager = this.blockRenderer.getBlockModelShaper().getModelManager(); ModelResourceLocation modelResourceLocation = this.getFrameModelResourceLoc(renderState.isGlowFrame, itemStack); poseStack.pushPose(); poseStack.translate(-0.5F, -0.5F, -0.5F); this.blockRenderer .getModelRenderer() .renderModel( poseStack.last(), bufferSource.getBuffer(RenderType.entitySolidZOffsetForward(TextureAtlas.LOCATION_BLOCKS)), null, modelManager.getModel(modelResourceLocation), 1.0F, 1.0F, 1.0F, packedLight, OverlayTexture.NO_OVERLAY ); poseStack.popPose(); } if (!itemStack.isEmpty()) { MapId mapId = renderState.mapId; if (renderState.isInvisible) { poseStack.translate(0.0F, 0.0F, 0.5F); } else { poseStack.translate(0.0F, 0.0F, 0.4375F); } int i = mapId != null ? renderState.rotation % 4 * 2 : renderState.rotation; poseStack.mulPose(Axis.ZP.rotationDegrees(i * 360.0F / 8.0F)); if (mapId != null) { poseStack.mulPose(Axis.ZP.rotationDegrees(180.0F)); float h = 0.0078125F; poseStack.scale(0.0078125F, 0.0078125F, 0.0078125F); poseStack.translate(-64.0F, -64.0F, 0.0F); poseStack.translate(0.0F, 0.0F, -1.0F); int j = this.getLightVal(renderState.isGlowFrame, 15728850, packedLight); this.mapRenderer.render(renderState.mapRenderState, poseStack, bufferSource, true, j); } else if (renderState.itemModel != null) { int k = this.getLightVal(renderState.isGlowFrame, 15728880, packedLight); poseStack.scale(0.5F, 0.5F, 0.5F); this.itemRenderer.render(itemStack, ItemDisplayContext.FIXED, false, poseStack, bufferSource, k, OverlayTexture.NO_OVERLAY, renderState.itemModel); } } poseStack.popPose(); } private int getLightVal(boolean isGlowFrame, int glowLightValue, int lightValue) { return isGlowFrame ? glowLightValue : lightValue; } private ModelResourceLocation getFrameModelResourceLoc(boolean isGlowFrame, ItemStack stack) { if (stack.has(DataComponents.MAP_ID)) { return isGlowFrame ? BlockStateModelLoader.GLOW_MAP_FRAME_LOCATION : BlockStateModelLoader.MAP_FRAME_LOCATION; } else { return isGlowFrame ? BlockStateModelLoader.GLOW_FRAME_LOCATION : BlockStateModelLoader.FRAME_LOCATION; } } public Vec3 getRenderOffset(ItemFrameRenderState renderState) { return new Vec3(renderState.direction.getStepX() * 0.3F, -0.25, renderState.direction.getStepZ() * 0.3F); } protected boolean shouldShowName(T entity, double distanceToCameraSq) { return Minecraft.renderNames() && !entity.getItem().isEmpty() && entity.getItem().has(DataComponents.CUSTOM_NAME) && this.entityRenderDispatcher.crosshairPickEntity == entity; } protected Component getNameTag(T entity) { return entity.getItem().getHoverName(); } public ItemFrameRenderState createRenderState() { return new ItemFrameRenderState(); } public void extractRenderState(T entity, ItemFrameRenderState reusedState, float partialTick) { super.extractRenderState(entity, reusedState, partialTick); reusedState.direction = entity.getDirection(); ItemStack itemStack = entity.getItem(); reusedState.itemStack = itemStack.copy(); reusedState.rotation = entity.getRotation(); reusedState.isGlowFrame = entity.getType() == EntityType.GLOW_ITEM_FRAME; reusedState.itemModel = null; reusedState.mapId = null; if (!reusedState.itemStack.isEmpty()) { MapId mapId = entity.getFramedMapId(itemStack); if (mapId != null) { MapItemSavedData mapItemSavedData = entity.level().getMapData(mapId); if (mapItemSavedData != null) { this.mapRenderer.extractRenderState(mapId, mapItemSavedData, reusedState.mapRenderState); reusedState.mapId = mapId; } } else { reusedState.itemModel = this.itemRenderer.getModel(itemStack, entity.level(), null, entity.getId()); } } } }