File size: 13,463 Bytes
d46f4a3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
package net.minecraft.client.renderer.entity;

import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import com.mojang.math.Axis;
import com.mojang.math.Transformation;
import java.util.ArrayList;
import java.util.List;
import net.minecraft.client.Camera;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Font;
import net.minecraft.client.renderer.LightTexture;
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.BlockDisplayEntityRenderState;
import net.minecraft.client.renderer.entity.state.DisplayEntityRenderState;
import net.minecraft.client.renderer.entity.state.ItemDisplayEntityRenderState;
import net.minecraft.client.renderer.entity.state.TextDisplayEntityRenderState;
import net.minecraft.client.renderer.item.ItemModelResolver;
import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component;
import net.minecraft.util.FormattedCharSequence;
import net.minecraft.world.entity.Display;
import net.minecraft.world.phys.AABB;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.joml.Matrix4f;
import org.joml.Quaternionf;

@OnlyIn(Dist.CLIENT)
public abstract class DisplayRenderer<T extends Display, S, ST extends DisplayEntityRenderState> extends EntityRenderer<T, ST> {
    private final EntityRenderDispatcher entityRenderDispatcher;

    protected DisplayRenderer(EntityRendererProvider.Context p_270168_) {
        super(p_270168_);
        this.entityRenderDispatcher = p_270168_.getEntityRenderDispatcher();
    }

    protected AABB getBoundingBoxForCulling(T p_368254_) {
        return p_368254_.getBoundingBoxForCulling();
    }

    protected boolean affectedByCulling(T p_365810_) {
        return p_365810_.affectedByCulling();
    }

    private static int getBrightnessOverride(Display p_365446_) {
        Display.RenderState display$renderstate = p_365446_.renderState();
        return display$renderstate != null ? display$renderstate.brightnessOverride() : -1;
    }

    protected int getSkyLightLevel(T p_367797_, BlockPos p_364805_) {
        int i = getBrightnessOverride(p_367797_);
        return i != -1 ? LightTexture.sky(i) : super.getSkyLightLevel(p_367797_, p_364805_);
    }

    protected int getBlockLightLevel(T p_362888_, BlockPos p_365686_) {
        int i = getBrightnessOverride(p_362888_);
        return i != -1 ? LightTexture.block(i) : super.getBlockLightLevel(p_362888_, p_365686_);
    }

    protected float getShadowRadius(ST p_376159_) {
        Display.RenderState display$renderstate = p_376159_.renderState;
        return display$renderstate == null ? 0.0F : display$renderstate.shadowRadius().get(p_376159_.interpolationProgress);
    }

    protected float getShadowStrength(ST p_377182_) {
        Display.RenderState display$renderstate = p_377182_.renderState;
        return display$renderstate == null ? 0.0F : display$renderstate.shadowStrength().get(p_377182_.interpolationProgress);
    }

    public void render(ST p_363838_, PoseStack p_270117_, MultiBufferSource p_270319_, int p_270659_) {
        Display.RenderState display$renderstate = p_363838_.renderState;
        if (display$renderstate != null && p_363838_.hasSubState()) {
            float f = p_363838_.interpolationProgress;
            super.render(p_363838_, p_270117_, p_270319_, p_270659_);
            p_270117_.pushPose();
            p_270117_.mulPose(this.calculateOrientation(display$renderstate, p_363838_, new Quaternionf()));
            Transformation transformation = display$renderstate.transformation().get(f);
            p_270117_.mulPose(transformation.getMatrix());
            this.renderInner(p_363838_, p_270117_, p_270319_, p_270659_, f);
            p_270117_.popPose();
        }
    }

    private Quaternionf calculateOrientation(Display.RenderState p_277846_, ST p_361564_, Quaternionf p_298476_) {
        Camera camera = this.entityRenderDispatcher.camera;

        return switch (p_277846_.billboardConstraints()) {
            case FIXED -> p_298476_.rotationYXZ((float) (-Math.PI / 180.0) * p_361564_.entityYRot, (float) (Math.PI / 180.0) * p_361564_.entityXRot, 0.0F);
            case HORIZONTAL -> p_298476_.rotationYXZ((float) (-Math.PI / 180.0) * p_361564_.entityYRot, (float) (Math.PI / 180.0) * cameraXRot(camera), 0.0F);
            case VERTICAL -> p_298476_.rotationYXZ((float) (-Math.PI / 180.0) * cameraYrot(camera), (float) (Math.PI / 180.0) * p_361564_.entityXRot, 0.0F);
            case CENTER -> p_298476_.rotationYXZ((float) (-Math.PI / 180.0) * cameraYrot(camera), (float) (Math.PI / 180.0) * cameraXRot(camera), 0.0F);
        };
    }

    private static float cameraYrot(Camera p_299213_) {
        return p_299213_.getYRot() - 180.0F;
    }

    private static float cameraXRot(Camera p_297923_) {
        return -p_297923_.getXRot();
    }

    private static <T extends Display> float entityYRot(T p_297849_, float p_297686_) {
        return p_297849_.getYRot(p_297686_);
    }

    private static <T extends Display> float entityXRot(T p_298651_, float p_297691_) {
        return p_298651_.getXRot(p_297691_);
    }

    protected abstract void renderInner(ST p_361844_, PoseStack p_277686_, MultiBufferSource p_277429_, int p_278023_, float p_277453_);

    public void extractRenderState(T p_364120_, ST p_362498_, float p_362522_) {
        super.extractRenderState(p_364120_, p_362498_, p_362522_);
        p_362498_.renderState = p_364120_.renderState();
        p_362498_.interpolationProgress = p_364120_.calculateInterpolationProgress(p_362522_);
        p_362498_.entityYRot = entityYRot(p_364120_, p_362522_);
        p_362498_.entityXRot = entityXRot(p_364120_, p_362522_);
    }

    @OnlyIn(Dist.CLIENT)
    public static class BlockDisplayRenderer
        extends DisplayRenderer<Display.BlockDisplay, Display.BlockDisplay.BlockRenderState, BlockDisplayEntityRenderState> {
        private final BlockRenderDispatcher blockRenderer;

        protected BlockDisplayRenderer(EntityRendererProvider.Context p_270283_) {
            super(p_270283_);
            this.blockRenderer = p_270283_.getBlockRenderDispatcher();
        }

        public BlockDisplayEntityRenderState createRenderState() {
            return new BlockDisplayEntityRenderState();
        }

        public void extractRenderState(Display.BlockDisplay p_367120_, BlockDisplayEntityRenderState p_364696_, float p_367582_) {
            super.extractRenderState(p_367120_, p_364696_, p_367582_);
            p_364696_.blockRenderState = p_367120_.blockRenderState();
        }

        public void renderInner(BlockDisplayEntityRenderState p_363283_, PoseStack p_277831_, MultiBufferSource p_277554_, int p_278071_, float p_277847_) {
            this.blockRenderer.renderSingleBlock(p_363283_.blockRenderState.blockState(), p_277831_, p_277554_, p_278071_, OverlayTexture.NO_OVERLAY);
        }
    }

    @OnlyIn(Dist.CLIENT)
    public static class ItemDisplayRenderer extends DisplayRenderer<Display.ItemDisplay, Display.ItemDisplay.ItemRenderState, ItemDisplayEntityRenderState> {
        private final ItemModelResolver itemModelResolver;

        protected ItemDisplayRenderer(EntityRendererProvider.Context p_270110_) {
            super(p_270110_);
            this.itemModelResolver = p_270110_.getItemModelResolver();
        }

        public ItemDisplayEntityRenderState createRenderState() {
            return new ItemDisplayEntityRenderState();
        }

        public void extractRenderState(Display.ItemDisplay p_368800_, ItemDisplayEntityRenderState p_363947_, float p_365503_) {
            super.extractRenderState(p_368800_, p_363947_, p_365503_);
            Display.ItemDisplay.ItemRenderState display$itemdisplay$itemrenderstate = p_368800_.itemRenderState();
            if (display$itemdisplay$itemrenderstate != null) {
                this.itemModelResolver
                    .updateForNonLiving(p_363947_.item, display$itemdisplay$itemrenderstate.itemStack(), display$itemdisplay$itemrenderstate.itemTransform(), p_368800_);
            } else {
                p_363947_.item.clear();
            }
        }

        public void renderInner(ItemDisplayEntityRenderState p_361473_, PoseStack p_277361_, MultiBufferSource p_277912_, int p_277474_, float p_278032_) {
            if (!p_361473_.item.isEmpty()) {
                p_277361_.mulPose(Axis.YP.rotation((float) Math.PI));
                p_361473_.item.render(p_277361_, p_277912_, p_277474_, OverlayTexture.NO_OVERLAY);
            }
        }
    }

    @OnlyIn(Dist.CLIENT)
    public static class TextDisplayRenderer extends DisplayRenderer<Display.TextDisplay, Display.TextDisplay.TextRenderState, TextDisplayEntityRenderState> {
        private final Font font;

        protected TextDisplayRenderer(EntityRendererProvider.Context p_271012_) {
            super(p_271012_);
            this.font = p_271012_.getFont();
        }

        public TextDisplayEntityRenderState createRenderState() {
            return new TextDisplayEntityRenderState();
        }

        public void extractRenderState(Display.TextDisplay p_365496_, TextDisplayEntityRenderState p_366254_, float p_368471_) {
            super.extractRenderState(p_365496_, p_366254_, p_368471_);
            p_366254_.textRenderState = p_365496_.textRenderState();
            p_366254_.cachedInfo = p_365496_.cacheDisplay(this::splitLines);
        }

        private Display.TextDisplay.CachedInfo splitLines(Component p_270823_, int p_270893_) {
            List<FormattedCharSequence> list = this.font.split(p_270823_, p_270893_);
            List<Display.TextDisplay.CachedLine> list1 = new ArrayList<>(list.size());
            int i = 0;

            for (FormattedCharSequence formattedcharsequence : list) {
                int j = this.font.width(formattedcharsequence);
                i = Math.max(i, j);
                list1.add(new Display.TextDisplay.CachedLine(formattedcharsequence, j));
            }

            return new Display.TextDisplay.CachedInfo(list1, i);
        }

        public void renderInner(TextDisplayEntityRenderState p_366994_, PoseStack p_277536_, MultiBufferSource p_277845_, int p_278046_, float p_277769_) {
            Display.TextDisplay.TextRenderState display$textdisplay$textrenderstate = p_366994_.textRenderState;
            byte b0 = display$textdisplay$textrenderstate.flags();
            boolean flag = (b0 & 2) != 0;
            boolean flag1 = (b0 & 4) != 0;
            boolean flag2 = (b0 & 1) != 0;
            Display.TextDisplay.Align display$textdisplay$align = Display.TextDisplay.getAlign(b0);
            byte b1 = (byte)display$textdisplay$textrenderstate.textOpacity().get(p_277769_);
            int i;
            if (flag1) {
                float f = Minecraft.getInstance().options.getBackgroundOpacity(0.25F);
                i = (int)(f * 255.0F) << 24;
            } else {
                i = display$textdisplay$textrenderstate.backgroundColor().get(p_277769_);
            }

            float f2 = 0.0F;
            Matrix4f matrix4f = p_277536_.last().pose();
            matrix4f.rotate((float) Math.PI, 0.0F, 1.0F, 0.0F);
            matrix4f.scale(-0.025F, -0.025F, -0.025F);
            Display.TextDisplay.CachedInfo display$textdisplay$cachedinfo = p_366994_.cachedInfo;
            int j = 1;
            int k = 9 + 1;
            int l = display$textdisplay$cachedinfo.width();
            int i1 = display$textdisplay$cachedinfo.lines().size() * k - 1;
            matrix4f.translate(1.0F - (float)l / 2.0F, (float)(-i1), 0.0F);
            if (i != 0) {
                VertexConsumer vertexconsumer = p_277845_.getBuffer(flag ? RenderType.textBackgroundSeeThrough() : RenderType.textBackground());
                vertexconsumer.addVertex(matrix4f, -1.0F, -1.0F, 0.0F).setColor(i).setLight(p_278046_);
                vertexconsumer.addVertex(matrix4f, -1.0F, (float)i1, 0.0F).setColor(i).setLight(p_278046_);
                vertexconsumer.addVertex(matrix4f, (float)l, (float)i1, 0.0F).setColor(i).setLight(p_278046_);
                vertexconsumer.addVertex(matrix4f, (float)l, -1.0F, 0.0F).setColor(i).setLight(p_278046_);
            }

            for (Display.TextDisplay.CachedLine display$textdisplay$cachedline : display$textdisplay$cachedinfo.lines()) {
                float f1 = switch (display$textdisplay$align) {
                    case LEFT -> 0.0F;
                    case RIGHT -> (float)(l - display$textdisplay$cachedline.width());
                    case CENTER -> (float)l / 2.0F - (float)display$textdisplay$cachedline.width() / 2.0F;
                };
                this.font
                    .drawInBatch(
                        display$textdisplay$cachedline.contents(),
                        f1,
                        f2,
                        b1 << 24 | 16777215,
                        flag2,
                        matrix4f,
                        p_277845_,
                        flag ? Font.DisplayMode.SEE_THROUGH : Font.DisplayMode.POLYGON_OFFSET,
                        0,
                        p_278046_
                    );
                f2 += (float)k;
            }
        }
    }
}