package net.minecraft.client.renderer.entity; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; 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.LevelRenderer; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.entity.EntityRendererProvider.Context; import net.minecraft.client.renderer.entity.state.PaintingRenderState; import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.resources.PaintingTextureManager; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.util.Mth; import net.minecraft.world.entity.decoration.Painting; import net.minecraft.world.entity.decoration.PaintingVariant; import net.minecraft.world.level.Level; @Environment(EnvType.CLIENT) public class PaintingRenderer extends EntityRenderer { public PaintingRenderer(Context context) { super(context); } public void render(PaintingRenderState paintingRenderState, PoseStack poseStack, MultiBufferSource multiBufferSource, int i) { PaintingVariant paintingVariant = paintingRenderState.variant; if (paintingVariant != null) { poseStack.pushPose(); poseStack.mulPose(Axis.YP.rotationDegrees(180 - paintingRenderState.direction.get2DDataValue() * 90)); PaintingTextureManager paintingTextureManager = Minecraft.getInstance().getPaintingTextures(); TextureAtlasSprite textureAtlasSprite = paintingTextureManager.getBackSprite(); VertexConsumer vertexConsumer = multiBufferSource.getBuffer(RenderType.entitySolidZOffsetForward(textureAtlasSprite.atlasLocation())); this.renderPainting( poseStack, vertexConsumer, paintingRenderState.lightCoords, paintingVariant.width(), paintingVariant.height(), paintingTextureManager.get(paintingVariant), textureAtlasSprite ); poseStack.popPose(); super.render(paintingRenderState, poseStack, multiBufferSource, i); } } public PaintingRenderState createRenderState() { return new PaintingRenderState(); } public void extractRenderState(Painting painting, PaintingRenderState paintingRenderState, float f) { super.extractRenderState(painting, paintingRenderState, f); Direction direction = painting.getDirection(); PaintingVariant paintingVariant = painting.getVariant().value(); paintingRenderState.direction = direction; paintingRenderState.variant = paintingVariant; int i = paintingVariant.width(); int j = paintingVariant.height(); if (paintingRenderState.lightCoords.length != i * j) { paintingRenderState.lightCoords = new int[i * j]; } float g = -i / 2.0F; float h = -j / 2.0F; Level level = painting.level(); for (int k = 0; k < j; k++) { for (int l = 0; l < i; l++) { float m = l + g + 0.5F; float n = k + h + 0.5F; int o = painting.getBlockX(); int p = Mth.floor(painting.getY() + n); int q = painting.getBlockZ(); switch (direction) { case NORTH: o = Mth.floor(painting.getX() + m); break; case WEST: q = Mth.floor(painting.getZ() - m); break; case SOUTH: o = Mth.floor(painting.getX() - m); break; case EAST: q = Mth.floor(painting.getZ() + m); } paintingRenderState.lightCoords[l + k * i] = LevelRenderer.getLightColor(level, new BlockPos(o, p, q)); } } } private void renderPainting( PoseStack poseStack, VertexConsumer buffer, int[] lightCoords, int width, int height, TextureAtlasSprite frontSprite, TextureAtlasSprite backSprite ) { PoseStack.Pose pose = poseStack.last(); float f = -width / 2.0F; float g = -height / 2.0F; float h = 0.03125F; float i = backSprite.getU0(); float j = backSprite.getU1(); float k = backSprite.getV0(); float l = backSprite.getV1(); float m = backSprite.getU0(); float n = backSprite.getU1(); float o = backSprite.getV0(); float p = backSprite.getV(0.0625F); float q = backSprite.getU0(); float r = backSprite.getU(0.0625F); float s = backSprite.getV0(); float t = backSprite.getV1(); double d = 1.0 / width; double e = 1.0 / height; for (int u = 0; u < width; u++) { for (int v = 0; v < height; v++) { float w = f + (u + 1); float x = f + u; float y = g + (v + 1); float z = g + v; int aa = lightCoords[u + v * width]; float ab = frontSprite.getU((float)(d * (width - u))); float ac = frontSprite.getU((float)(d * (width - (u + 1)))); float ad = frontSprite.getV((float)(e * (height - v))); float ae = frontSprite.getV((float)(e * (height - (v + 1)))); this.vertex(pose, buffer, w, z, ac, ad, -0.03125F, 0, 0, -1, aa); this.vertex(pose, buffer, x, z, ab, ad, -0.03125F, 0, 0, -1, aa); this.vertex(pose, buffer, x, y, ab, ae, -0.03125F, 0, 0, -1, aa); this.vertex(pose, buffer, w, y, ac, ae, -0.03125F, 0, 0, -1, aa); this.vertex(pose, buffer, w, y, j, k, 0.03125F, 0, 0, 1, aa); this.vertex(pose, buffer, x, y, i, k, 0.03125F, 0, 0, 1, aa); this.vertex(pose, buffer, x, z, i, l, 0.03125F, 0, 0, 1, aa); this.vertex(pose, buffer, w, z, j, l, 0.03125F, 0, 0, 1, aa); this.vertex(pose, buffer, w, y, m, o, -0.03125F, 0, 1, 0, aa); this.vertex(pose, buffer, x, y, n, o, -0.03125F, 0, 1, 0, aa); this.vertex(pose, buffer, x, y, n, p, 0.03125F, 0, 1, 0, aa); this.vertex(pose, buffer, w, y, m, p, 0.03125F, 0, 1, 0, aa); this.vertex(pose, buffer, w, z, m, o, 0.03125F, 0, -1, 0, aa); this.vertex(pose, buffer, x, z, n, o, 0.03125F, 0, -1, 0, aa); this.vertex(pose, buffer, x, z, n, p, -0.03125F, 0, -1, 0, aa); this.vertex(pose, buffer, w, z, m, p, -0.03125F, 0, -1, 0, aa); this.vertex(pose, buffer, w, y, r, s, 0.03125F, -1, 0, 0, aa); this.vertex(pose, buffer, w, z, r, t, 0.03125F, -1, 0, 0, aa); this.vertex(pose, buffer, w, z, q, t, -0.03125F, -1, 0, 0, aa); this.vertex(pose, buffer, w, y, q, s, -0.03125F, -1, 0, 0, aa); this.vertex(pose, buffer, x, y, r, s, -0.03125F, 1, 0, 0, aa); this.vertex(pose, buffer, x, z, r, t, -0.03125F, 1, 0, 0, aa); this.vertex(pose, buffer, x, z, q, t, 0.03125F, 1, 0, 0, aa); this.vertex(pose, buffer, x, y, q, s, 0.03125F, 1, 0, 0, aa); } } } private void vertex( PoseStack.Pose pose, VertexConsumer consumer, float x, float y, float u, float v, float z, int normalX, int normalY, int normalZ, int packedLight ) { consumer.addVertex(pose, x, y, z) .setColor(-1) .setUv(u, v) .setOverlay(OverlayTexture.NO_OVERLAY) .setLight(packedLight) .setNormal(pose, normalX, normalY, normalZ); } }