package net.minecraft.client.renderer.item; import com.mojang.blaze3d.vertex.PoseStack; import java.util.Arrays; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.block.model.ItemTransform; import net.minecraft.client.renderer.entity.ItemRenderer; import net.minecraft.client.renderer.special.SpecialModelRenderer; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.resources.model.BakedModel; import net.minecraft.util.RandomSource; import net.minecraft.world.item.ItemDisplayContext; import org.jetbrains.annotations.Nullable; @Environment(EnvType.CLIENT) public class ItemStackRenderState { ItemDisplayContext displayContext = ItemDisplayContext.NONE; boolean isLeftHand; private int activeLayerCount; private ItemStackRenderState.LayerRenderState[] layers = new ItemStackRenderState.LayerRenderState[]{new ItemStackRenderState.LayerRenderState()}; public void ensureCapacity(int expectedSize) { int i = this.layers.length; int j = this.activeLayerCount + expectedSize; if (j > i) { this.layers = (ItemStackRenderState.LayerRenderState[])Arrays.copyOf(this.layers, j); for (int k = i; k < j; k++) { this.layers[k] = new ItemStackRenderState.LayerRenderState(); } } } public ItemStackRenderState.LayerRenderState newLayer() { this.ensureCapacity(1); return this.layers[this.activeLayerCount++]; } public void clear() { this.displayContext = ItemDisplayContext.NONE; this.isLeftHand = false; for (int i = 0; i < this.activeLayerCount; i++) { this.layers[i].clear(); } this.activeLayerCount = 0; } private ItemStackRenderState.LayerRenderState firstLayer() { return this.layers[0]; } public boolean isEmpty() { return this.activeLayerCount == 0; } public boolean isGui3d() { return this.firstLayer().isGui3d(); } public boolean usesBlockLight() { return this.firstLayer().usesBlockLight(); } @Nullable public TextureAtlasSprite pickParticleIcon(RandomSource random) { if (this.activeLayerCount == 0) { return null; } else { BakedModel bakedModel = this.layers[random.nextInt(this.activeLayerCount)].model; return bakedModel == null ? null : bakedModel.getParticleIcon(); } } public ItemTransform transform() { return this.firstLayer().transform(); } public void render(PoseStack poseStack, MultiBufferSource bufferSource, int packedLight, int packedOverlay) { for (int i = 0; i < this.activeLayerCount; i++) { this.layers[i].render(poseStack, bufferSource, packedLight, packedOverlay); } } @Environment(EnvType.CLIENT) public static enum FoilType { NONE, STANDARD, SPECIAL; } @Environment(EnvType.CLIENT) public class LayerRenderState { @Nullable BakedModel model; @Nullable private RenderType renderType; private ItemStackRenderState.FoilType foilType = ItemStackRenderState.FoilType.NONE; private int[] tintLayers = new int[0]; @Nullable private SpecialModelRenderer specialRenderer; @Nullable private Object argumentForSpecialRendering; public void clear() { this.model = null; this.renderType = null; this.foilType = ItemStackRenderState.FoilType.NONE; this.specialRenderer = null; this.argumentForSpecialRendering = null; Arrays.fill(this.tintLayers, -1); } public void setupBlockModel(BakedModel model, RenderType renderType) { this.model = model; this.renderType = renderType; } public void setupSpecialModel(SpecialModelRenderer specialRenderer, @Nullable T argumentForSpecialRendering, BakedModel model) { this.model = model; this.specialRenderer = eraseSpecialRenderer(specialRenderer); this.argumentForSpecialRendering = argumentForSpecialRendering; } private static SpecialModelRenderer eraseSpecialRenderer(SpecialModelRenderer specialRenderer) { return (SpecialModelRenderer)specialRenderer; } public void setFoilType(ItemStackRenderState.FoilType foilType) { this.foilType = foilType; } public int[] prepareTintLayers(int count) { if (count > this.tintLayers.length) { this.tintLayers = new int[count]; Arrays.fill(this.tintLayers, -1); } return this.tintLayers; } ItemTransform transform() { return this.model != null ? this.model.getTransforms().getTransform(ItemStackRenderState.this.displayContext) : ItemTransform.NO_TRANSFORM; } void render(PoseStack poseStack, MultiBufferSource bufferSource, int packedLight, int packedOverlay) { poseStack.pushPose(); this.transform().apply(ItemStackRenderState.this.isLeftHand, poseStack); poseStack.translate(-0.5F, -0.5F, -0.5F); if (this.specialRenderer != null) { this.specialRenderer .render( this.argumentForSpecialRendering, ItemStackRenderState.this.displayContext, poseStack, bufferSource, packedLight, packedOverlay, this.foilType != ItemStackRenderState.FoilType.NONE ); } else if (this.model != null) { ItemRenderer.renderItem( ItemStackRenderState.this.displayContext, poseStack, bufferSource, packedLight, packedOverlay, this.tintLayers, this.model, this.renderType, this.foilType ); } poseStack.popPose(); } boolean isGui3d() { return this.model != null && this.model.isGui3d(); } boolean usesBlockLight() { return this.model != null && this.model.usesBlockLight(); } } }