minecraft-src/net/minecraft/client/renderer/entity/ItemRenderer.java
2025-07-04 03:15:13 +03:00

168 lines
6.4 KiB
Java

package net.minecraft.client.renderer.entity;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.SheetedDecalTextureGenerator;
import com.mojang.blaze3d.vertex.VertexConsumer;
import com.mojang.blaze3d.vertex.VertexMultiConsumer;
import com.mojang.blaze3d.vertex.PoseStack.Pose;
import com.mojang.math.MatrixUtil;
import java.util.List;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.Sheets;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.item.ItemModelResolver;
import net.minecraft.client.renderer.item.ItemStackRenderState;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.core.Direction;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.ARGB;
import net.minecraft.util.RandomSource;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.item.ItemDisplayContext;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import org.jetbrains.annotations.Nullable;
@Environment(EnvType.CLIENT)
public class ItemRenderer {
public static final ResourceLocation ENCHANTED_GLINT_ENTITY = ResourceLocation.withDefaultNamespace("textures/misc/enchanted_glint_entity.png");
public static final ResourceLocation ENCHANTED_GLINT_ITEM = ResourceLocation.withDefaultNamespace("textures/misc/enchanted_glint_item.png");
public static final int GUI_SLOT_CENTER_X = 8;
public static final int GUI_SLOT_CENTER_Y = 8;
public static final int ITEM_DECORATION_BLIT_OFFSET = 200;
public static final float COMPASS_FOIL_UI_SCALE = 0.5F;
public static final float COMPASS_FOIL_FIRST_PERSON_SCALE = 0.75F;
public static final float COMPASS_FOIL_TEXTURE_SCALE = 0.0078125F;
public static final int NO_TINT = -1;
private final ItemModelResolver resolver;
private final ItemStackRenderState scratchItemStackRenderState = new ItemStackRenderState();
public ItemRenderer(ItemModelResolver resolver) {
this.resolver = resolver;
}
private static void renderModelLists(BakedModel model, int[] tintLayers, int packedLight, int packedOverlay, PoseStack poseStack, VertexConsumer buffer) {
RandomSource randomSource = RandomSource.create();
long l = 42L;
for (Direction direction : Direction.values()) {
randomSource.setSeed(42L);
renderQuadList(poseStack, buffer, model.getQuads(null, direction, randomSource), tintLayers, packedLight, packedOverlay);
}
randomSource.setSeed(42L);
renderQuadList(poseStack, buffer, model.getQuads(null, null, randomSource), tintLayers, packedLight, packedOverlay);
}
public static void renderItem(
ItemDisplayContext displayContext,
PoseStack poseStack,
MultiBufferSource bufferSource,
int packedLight,
int packedOverlay,
int[] tintLayers,
BakedModel model,
RenderType renderType,
ItemStackRenderState.FoilType foilType
) {
VertexConsumer vertexConsumer;
if (foilType == ItemStackRenderState.FoilType.SPECIAL) {
Pose pose = poseStack.last().copy();
if (displayContext == ItemDisplayContext.GUI) {
MatrixUtil.mulComponentWise(pose.pose(), 0.5F);
} else if (displayContext.firstPerson()) {
MatrixUtil.mulComponentWise(pose.pose(), 0.75F);
}
vertexConsumer = getCompassFoilBuffer(bufferSource, renderType, pose);
} else {
vertexConsumer = getFoilBuffer(bufferSource, renderType, true, foilType != ItemStackRenderState.FoilType.NONE);
}
renderModelLists(model, tintLayers, packedLight, packedOverlay, poseStack, vertexConsumer);
}
public static VertexConsumer getArmorFoilBuffer(MultiBufferSource bufferSource, RenderType renderType, boolean hasFoil) {
return hasFoil
? VertexMultiConsumer.create(bufferSource.getBuffer(RenderType.armorEntityGlint()), bufferSource.getBuffer(renderType))
: bufferSource.getBuffer(renderType);
}
private static VertexConsumer getCompassFoilBuffer(MultiBufferSource bufferSource, RenderType renderType, Pose pose) {
return VertexMultiConsumer.create(
new SheetedDecalTextureGenerator(bufferSource.getBuffer(RenderType.glint()), pose, 0.0078125F), bufferSource.getBuffer(renderType)
);
}
public static VertexConsumer getFoilBuffer(MultiBufferSource bufferSource, RenderType renderType, boolean isItem, boolean glint) {
if (glint) {
return Minecraft.useShaderTransparency() && renderType == Sheets.translucentItemSheet()
? VertexMultiConsumer.create(bufferSource.getBuffer(RenderType.glintTranslucent()), bufferSource.getBuffer(renderType))
: VertexMultiConsumer.create(bufferSource.getBuffer(isItem ? RenderType.glint() : RenderType.entityGlint()), bufferSource.getBuffer(renderType));
} else {
return bufferSource.getBuffer(renderType);
}
}
private static int getLayerColorSafe(int[] tintLayers, int index) {
return index >= tintLayers.length ? -1 : tintLayers[index];
}
private static void renderQuadList(PoseStack poseStack, VertexConsumer buffer, List<BakedQuad> quads, int[] tintLayers, int packedLight, int packedOverlay) {
Pose pose = poseStack.last();
for (BakedQuad bakedQuad : quads) {
float f;
float g;
float h;
float j;
if (bakedQuad.isTinted()) {
int i = getLayerColorSafe(tintLayers, bakedQuad.getTintIndex());
f = ARGB.alpha(i) / 255.0F;
g = ARGB.red(i) / 255.0F;
h = ARGB.green(i) / 255.0F;
j = ARGB.blue(i) / 255.0F;
} else {
f = 1.0F;
g = 1.0F;
h = 1.0F;
j = 1.0F;
}
buffer.putBulkData(pose, bakedQuad, g, h, j, f, packedLight, packedOverlay);
}
}
public void renderStatic(
ItemStack stack,
ItemDisplayContext displayContext,
int combinedLight,
int combinedOverlay,
PoseStack poseStack,
MultiBufferSource bufferSource,
@Nullable Level level,
int seed
) {
this.renderStatic(null, stack, displayContext, false, poseStack, bufferSource, level, combinedLight, combinedOverlay, seed);
}
public void renderStatic(
@Nullable LivingEntity entity,
ItemStack itemStack,
ItemDisplayContext diplayContext,
boolean leftHand,
PoseStack poseStack,
MultiBufferSource bufferSource,
@Nullable Level level,
int combinedLight,
int combinedOverlay,
int seed
) {
this.resolver.updateForTopItem(this.scratchItemStackRenderState, itemStack, diplayContext, leftHand, level, entity, seed);
this.scratchItemStackRenderState.render(poseStack, bufferSource, combinedLight, combinedOverlay);
}
}