001package net.minecraft.client.renderer.entity;
002
003import cpw.mods.fml.relauncher.Side;
004import cpw.mods.fml.relauncher.SideOnly;
005import java.util.Random;
006import net.minecraft.client.Minecraft;
007import net.minecraft.client.gui.FontRenderer;
008import net.minecraft.client.model.ModelBase;
009import net.minecraft.client.model.ModelBox;
010import net.minecraft.client.model.ModelRenderer;
011import net.minecraft.client.renderer.OpenGlHelper;
012import net.minecraft.client.renderer.RenderHelper;
013import net.minecraft.client.renderer.Tessellator;
014import net.minecraft.entity.Entity;
015import net.minecraft.entity.EntityLiving;
016import net.minecraft.entity.projectile.EntityArrow;
017import net.minecraft.util.MathHelper;
018import org.lwjgl.opengl.GL11;
019import org.lwjgl.opengl.GL12;
020
021@SideOnly(Side.CLIENT)
022public class RenderLiving extends Render
023{
024    protected ModelBase mainModel;
025
026    /** The model to be used during the render passes. */
027    protected ModelBase renderPassModel;
028
029    public RenderLiving(ModelBase par1ModelBase, float par2)
030    {
031        this.mainModel = par1ModelBase;
032        this.shadowSize = par2;
033    }
034
035    /**
036     * Sets the model to be used in the current render pass (the first render pass is done after the primary model is
037     * rendered) Args: model
038     */
039    public void setRenderPassModel(ModelBase par1ModelBase)
040    {
041        this.renderPassModel = par1ModelBase;
042    }
043
044    /**
045     * Returns a rotation angle that is inbetween two other rotation angles. par1 and par2 are the angles between which
046     * to interpolate, par3 is probably a float between 0.0 and 1.0 that tells us where "between" the two angles we are.
047     * Example: par1 = 30, par2 = 50, par3 = 0.5, then return = 40
048     */
049    private float interpolateRotation(float par1, float par2, float par3)
050    {
051        float var4;
052
053        for (var4 = par2 - par1; var4 < -180.0F; var4 += 360.0F)
054        {
055            ;
056        }
057
058        while (var4 >= 180.0F)
059        {
060            var4 -= 360.0F;
061        }
062
063        return par1 + par3 * var4;
064    }
065
066    public void doRenderLiving(EntityLiving par1EntityLiving, double par2, double par4, double par6, float par8, float par9)
067    {
068        GL11.glPushMatrix();
069        GL11.glDisable(GL11.GL_CULL_FACE);
070        this.mainModel.onGround = this.renderSwingProgress(par1EntityLiving, par9);
071
072        if (this.renderPassModel != null)
073        {
074            this.renderPassModel.onGround = this.mainModel.onGround;
075        }
076
077        this.mainModel.isRiding = par1EntityLiving.isRiding();
078
079        if (this.renderPassModel != null)
080        {
081            this.renderPassModel.isRiding = this.mainModel.isRiding;
082        }
083
084        this.mainModel.isChild = par1EntityLiving.isChild();
085
086        if (this.renderPassModel != null)
087        {
088            this.renderPassModel.isChild = this.mainModel.isChild;
089        }
090
091        try
092        {
093            float var10 = this.interpolateRotation(par1EntityLiving.prevRenderYawOffset, par1EntityLiving.renderYawOffset, par9);
094            float var11 = this.interpolateRotation(par1EntityLiving.prevRotationYawHead, par1EntityLiving.rotationYawHead, par9);
095            float var12 = par1EntityLiving.prevRotationPitch + (par1EntityLiving.rotationPitch - par1EntityLiving.prevRotationPitch) * par9;
096            this.renderLivingAt(par1EntityLiving, par2, par4, par6);
097            float var13 = this.handleRotationFloat(par1EntityLiving, par9);
098            this.rotateCorpse(par1EntityLiving, var13, var10, par9);
099            float var14 = 0.0625F;
100            GL11.glEnable(GL12.GL_RESCALE_NORMAL);
101            GL11.glScalef(-1.0F, -1.0F, 1.0F);
102            this.preRenderCallback(par1EntityLiving, par9);
103            GL11.glTranslatef(0.0F, -24.0F * var14 - 0.0078125F, 0.0F);
104            float var15 = par1EntityLiving.prevLegYaw + (par1EntityLiving.legYaw - par1EntityLiving.prevLegYaw) * par9;
105            float var16 = par1EntityLiving.legSwing - par1EntityLiving.legYaw * (1.0F - par9);
106
107            if (par1EntityLiving.isChild())
108            {
109                var16 *= 3.0F;
110            }
111
112            if (var15 > 1.0F)
113            {
114                var15 = 1.0F;
115            }
116
117            GL11.glEnable(GL11.GL_ALPHA_TEST);
118            this.mainModel.setLivingAnimations(par1EntityLiving, var16, var15, par9);
119            this.renderModel(par1EntityLiving, var16, var15, var13, var11 - var10, var12, var14);
120            float var19;
121            int var18;
122            float var20;
123            float var22;
124
125            for (int var17 = 0; var17 < 4; ++var17)
126            {
127                var18 = this.shouldRenderPass(par1EntityLiving, var17, par9);
128
129                if (var18 > 0)
130                {
131                    this.renderPassModel.setLivingAnimations(par1EntityLiving, var16, var15, par9);
132                    this.renderPassModel.render(par1EntityLiving, var16, var15, var13, var11 - var10, var12, var14);
133
134                    if ((var18 & 240) == 16)
135                    {
136                        this.func_82408_c(par1EntityLiving, var17, par9);
137                        this.renderPassModel.render(par1EntityLiving, var16, var15, var13, var11 - var10, var12, var14);
138                    }
139
140                    if ((var18 & 15) == 15)
141                    {
142                        var19 = (float)par1EntityLiving.ticksExisted + par9;
143                        this.loadTexture("%blur%/misc/glint.png");
144                        GL11.glEnable(GL11.GL_BLEND);
145                        var20 = 0.5F;
146                        GL11.glColor4f(var20, var20, var20, 1.0F);
147                        GL11.glDepthFunc(GL11.GL_EQUAL);
148                        GL11.glDepthMask(false);
149
150                        for (int var21 = 0; var21 < 2; ++var21)
151                        {
152                            GL11.glDisable(GL11.GL_LIGHTING);
153                            var22 = 0.76F;
154                            GL11.glColor4f(0.5F * var22, 0.25F * var22, 0.8F * var22, 1.0F);
155                            GL11.glBlendFunc(GL11.GL_SRC_COLOR, GL11.GL_ONE);
156                            GL11.glMatrixMode(GL11.GL_TEXTURE);
157                            GL11.glLoadIdentity();
158                            float var23 = var19 * (0.001F + (float)var21 * 0.003F) * 20.0F;
159                            float var24 = 0.33333334F;
160                            GL11.glScalef(var24, var24, var24);
161                            GL11.glRotatef(30.0F - (float)var21 * 60.0F, 0.0F, 0.0F, 1.0F);
162                            GL11.glTranslatef(0.0F, var23, 0.0F);
163                            GL11.glMatrixMode(GL11.GL_MODELVIEW);
164                            this.renderPassModel.render(par1EntityLiving, var16, var15, var13, var11 - var10, var12, var14);
165                        }
166
167                        GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
168                        GL11.glMatrixMode(GL11.GL_TEXTURE);
169                        GL11.glDepthMask(true);
170                        GL11.glLoadIdentity();
171                        GL11.glMatrixMode(GL11.GL_MODELVIEW);
172                        GL11.glEnable(GL11.GL_LIGHTING);
173                        GL11.glDisable(GL11.GL_BLEND);
174                        GL11.glDepthFunc(GL11.GL_LEQUAL);
175                    }
176
177                    GL11.glDisable(GL11.GL_BLEND);
178                    GL11.glEnable(GL11.GL_ALPHA_TEST);
179                }
180            }
181
182            GL11.glDepthMask(true);
183            this.renderEquippedItems(par1EntityLiving, par9);
184            float var26 = par1EntityLiving.getBrightness(par9);
185            var18 = this.getColorMultiplier(par1EntityLiving, var26, par9);
186            OpenGlHelper.setActiveTexture(OpenGlHelper.lightmapTexUnit);
187            GL11.glDisable(GL11.GL_TEXTURE_2D);
188            OpenGlHelper.setActiveTexture(OpenGlHelper.defaultTexUnit);
189
190            if ((var18 >> 24 & 255) > 0 || par1EntityLiving.hurtTime > 0 || par1EntityLiving.deathTime > 0)
191            {
192                GL11.glDisable(GL11.GL_TEXTURE_2D);
193                GL11.glDisable(GL11.GL_ALPHA_TEST);
194                GL11.glEnable(GL11.GL_BLEND);
195                GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
196                GL11.glDepthFunc(GL11.GL_EQUAL);
197
198                if (par1EntityLiving.hurtTime > 0 || par1EntityLiving.deathTime > 0)
199                {
200                    GL11.glColor4f(var26, 0.0F, 0.0F, 0.4F);
201                    this.mainModel.render(par1EntityLiving, var16, var15, var13, var11 - var10, var12, var14);
202
203                    for (int var27 = 0; var27 < 4; ++var27)
204                    {
205                        if (this.inheritRenderPass(par1EntityLiving, var27, par9) >= 0)
206                        {
207                            GL11.glColor4f(var26, 0.0F, 0.0F, 0.4F);
208                            this.renderPassModel.render(par1EntityLiving, var16, var15, var13, var11 - var10, var12, var14);
209                        }
210                    }
211                }
212
213                if ((var18 >> 24 & 255) > 0)
214                {
215                    var19 = (float)(var18 >> 16 & 255) / 255.0F;
216                    var20 = (float)(var18 >> 8 & 255) / 255.0F;
217                    float var29 = (float)(var18 & 255) / 255.0F;
218                    var22 = (float)(var18 >> 24 & 255) / 255.0F;
219                    GL11.glColor4f(var19, var20, var29, var22);
220                    this.mainModel.render(par1EntityLiving, var16, var15, var13, var11 - var10, var12, var14);
221
222                    for (int var28 = 0; var28 < 4; ++var28)
223                    {
224                        if (this.inheritRenderPass(par1EntityLiving, var28, par9) >= 0)
225                        {
226                            GL11.glColor4f(var19, var20, var29, var22);
227                            this.renderPassModel.render(par1EntityLiving, var16, var15, var13, var11 - var10, var12, var14);
228                        }
229                    }
230                }
231
232                GL11.glDepthFunc(GL11.GL_LEQUAL);
233                GL11.glDisable(GL11.GL_BLEND);
234                GL11.glEnable(GL11.GL_ALPHA_TEST);
235                GL11.glEnable(GL11.GL_TEXTURE_2D);
236            }
237
238            GL11.glDisable(GL12.GL_RESCALE_NORMAL);
239        }
240        catch (Exception var25)
241        {
242            var25.printStackTrace();
243        }
244
245        OpenGlHelper.setActiveTexture(OpenGlHelper.lightmapTexUnit);
246        GL11.glEnable(GL11.GL_TEXTURE_2D);
247        OpenGlHelper.setActiveTexture(OpenGlHelper.defaultTexUnit);
248        GL11.glEnable(GL11.GL_CULL_FACE);
249        GL11.glPopMatrix();
250        this.passSpecialRender(par1EntityLiving, par2, par4, par6);
251    }
252
253    /**
254     * Renders the model in RenderLiving
255     */
256    protected void renderModel(EntityLiving par1EntityLiving, float par2, float par3, float par4, float par5, float par6, float par7)
257    {
258        if (!par1EntityLiving.getHasActivePotion())
259        {
260            this.loadDownloadableImageTexture(par1EntityLiving.skinUrl, par1EntityLiving.getTexture());
261            this.mainModel.render(par1EntityLiving, par2, par3, par4, par5, par6, par7);
262        }
263        else
264        {
265            this.mainModel.setRotationAngles(par2, par3, par4, par5, par6, par7, par1EntityLiving);
266        }
267    }
268
269    /**
270     * Sets a simple glTranslate on a LivingEntity.
271     */
272    protected void renderLivingAt(EntityLiving par1EntityLiving, double par2, double par4, double par6)
273    {
274        GL11.glTranslatef((float)par2, (float)par4, (float)par6);
275    }
276
277    protected void rotateCorpse(EntityLiving par1EntityLiving, float par2, float par3, float par4)
278    {
279        GL11.glRotatef(180.0F - par3, 0.0F, 1.0F, 0.0F);
280
281        if (par1EntityLiving.deathTime > 0)
282        {
283            float var5 = ((float)par1EntityLiving.deathTime + par4 - 1.0F) / 20.0F * 1.6F;
284            var5 = MathHelper.sqrt_float(var5);
285
286            if (var5 > 1.0F)
287            {
288                var5 = 1.0F;
289            }
290
291            GL11.glRotatef(var5 * this.getDeathMaxRotation(par1EntityLiving), 0.0F, 0.0F, 1.0F);
292        }
293    }
294
295    protected float renderSwingProgress(EntityLiving par1EntityLiving, float par2)
296    {
297        return par1EntityLiving.getSwingProgress(par2);
298    }
299
300    /**
301     * Defines what float the third param in setRotationAngles of ModelBase is
302     */
303    protected float handleRotationFloat(EntityLiving par1EntityLiving, float par2)
304    {
305        return (float)par1EntityLiving.ticksExisted + par2;
306    }
307
308    protected void renderEquippedItems(EntityLiving par1EntityLiving, float par2) {}
309
310    /**
311     * renders arrows the Entity has been attacked with, attached to it
312     */
313    protected void renderArrowsStuckInEntity(EntityLiving par1EntityLiving, float par2)
314    {
315        int var3 = par1EntityLiving.getArrowCountInEntity();
316
317        if (var3 > 0)
318        {
319            EntityArrow var4 = new EntityArrow(par1EntityLiving.worldObj, par1EntityLiving.posX, par1EntityLiving.posY, par1EntityLiving.posZ);
320            Random var5 = new Random((long)par1EntityLiving.entityId);
321            RenderHelper.disableStandardItemLighting();
322
323            for (int var6 = 0; var6 < var3; ++var6)
324            {
325                GL11.glPushMatrix();
326                ModelRenderer var7 = this.mainModel.func_85181_a(var5);
327                ModelBox var8 = (ModelBox)var7.cubeList.get(var5.nextInt(var7.cubeList.size()));
328                var7.postRender(0.0625F);
329                float var9 = var5.nextFloat();
330                float var10 = var5.nextFloat();
331                float var11 = var5.nextFloat();
332                float var12 = (var8.posX1 + (var8.posX2 - var8.posX1) * var9) / 16.0F;
333                float var13 = (var8.posY1 + (var8.posY2 - var8.posY1) * var10) / 16.0F;
334                float var14 = (var8.posZ1 + (var8.posZ2 - var8.posZ1) * var11) / 16.0F;
335                GL11.glTranslatef(var12, var13, var14);
336                var9 = var9 * 2.0F - 1.0F;
337                var10 = var10 * 2.0F - 1.0F;
338                var11 = var11 * 2.0F - 1.0F;
339                var9 *= -1.0F;
340                var10 *= -1.0F;
341                var11 *= -1.0F;
342                float var15 = MathHelper.sqrt_float(var9 * var9 + var11 * var11);
343                var4.prevRotationYaw = var4.rotationYaw = (float)(Math.atan2((double)var9, (double)var11) * 180.0D / Math.PI);
344                var4.prevRotationPitch = var4.rotationPitch = (float)(Math.atan2((double)var10, (double)var15) * 180.0D / Math.PI);
345                double var16 = 0.0D;
346                double var18 = 0.0D;
347                double var20 = 0.0D;
348                float var22 = 0.0F;
349                this.renderManager.renderEntityWithPosYaw(var4, var16, var18, var20, var22, par2);
350                GL11.glPopMatrix();
351            }
352
353            RenderHelper.enableStandardItemLighting();
354        }
355    }
356
357    protected int inheritRenderPass(EntityLiving par1EntityLiving, int par2, float par3)
358    {
359        return this.shouldRenderPass(par1EntityLiving, par2, par3);
360    }
361
362    /**
363     * Queries whether should render the specified pass or not.
364     */
365    protected int shouldRenderPass(EntityLiving par1EntityLiving, int par2, float par3)
366    {
367        return -1;
368    }
369
370    protected void func_82408_c(EntityLiving par1EntityLiving, int par2, float par3) {}
371
372    protected float getDeathMaxRotation(EntityLiving par1EntityLiving)
373    {
374        return 90.0F;
375    }
376
377    /**
378     * Returns an ARGB int color back. Args: entityLiving, lightBrightness, partialTickTime
379     */
380    protected int getColorMultiplier(EntityLiving par1EntityLiving, float par2, float par3)
381    {
382        return 0;
383    }
384
385    /**
386     * Allows the render to do any OpenGL state modifications necessary before the model is rendered. Args:
387     * entityLiving, partialTickTime
388     */
389    protected void preRenderCallback(EntityLiving par1EntityLiving, float par2) {}
390
391    /**
392     * Passes the specialRender and renders it
393     */
394    protected void passSpecialRender(EntityLiving par1EntityLiving, double par2, double par4, double par6)
395    {
396        if (Minecraft.isDebugInfoEnabled())
397        {
398            ;
399        }
400    }
401
402    /**
403     * Draws the debug or playername text above a living
404     */
405    protected void renderLivingLabel(EntityLiving par1EntityLiving, String par2Str, double par3, double par5, double par7, int par9)
406    {
407        double var10 = par1EntityLiving.getDistanceSqToEntity(this.renderManager.livingPlayer);
408
409        if (var10 <= (double)(par9 * par9))
410        {
411            FontRenderer var12 = this.getFontRendererFromRenderManager();
412            float var13 = 1.6F;
413            float var14 = 0.016666668F * var13;
414            GL11.glPushMatrix();
415            GL11.glTranslatef((float)par3 + 0.0F, (float)par5 + 2.3F, (float)par7);
416            GL11.glNormal3f(0.0F, 1.0F, 0.0F);
417            GL11.glRotatef(-this.renderManager.playerViewY, 0.0F, 1.0F, 0.0F);
418            GL11.glRotatef(this.renderManager.playerViewX, 1.0F, 0.0F, 0.0F);
419            GL11.glScalef(-var14, -var14, var14);
420            GL11.glDisable(GL11.GL_LIGHTING);
421            GL11.glDepthMask(false);
422            GL11.glDisable(GL11.GL_DEPTH_TEST);
423            GL11.glEnable(GL11.GL_BLEND);
424            GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
425            Tessellator var15 = Tessellator.instance;
426            byte var16 = 0;
427
428            if (par2Str.equals("deadmau5"))
429            {
430                var16 = -10;
431            }
432
433            GL11.glDisable(GL11.GL_TEXTURE_2D);
434            var15.startDrawingQuads();
435            int var17 = var12.getStringWidth(par2Str) / 2;
436            var15.setColorRGBA_F(0.0F, 0.0F, 0.0F, 0.25F);
437            var15.addVertex((double)(-var17 - 1), (double)(-1 + var16), 0.0D);
438            var15.addVertex((double)(-var17 - 1), (double)(8 + var16), 0.0D);
439            var15.addVertex((double)(var17 + 1), (double)(8 + var16), 0.0D);
440            var15.addVertex((double)(var17 + 1), (double)(-1 + var16), 0.0D);
441            var15.draw();
442            GL11.glEnable(GL11.GL_TEXTURE_2D);
443            var12.drawString(par2Str, -var12.getStringWidth(par2Str) / 2, var16, 553648127);
444            GL11.glEnable(GL11.GL_DEPTH_TEST);
445            GL11.glDepthMask(true);
446            var12.drawString(par2Str, -var12.getStringWidth(par2Str) / 2, var16, -1);
447            GL11.glEnable(GL11.GL_LIGHTING);
448            GL11.glDisable(GL11.GL_BLEND);
449            GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
450            GL11.glPopMatrix();
451        }
452    }
453
454    /**
455     * Actually renders the given argument. This is a synthetic bridge method, always casting down its argument and then
456     * handing it off to a worker function which does the actual work. In all probabilty, the class Render is generic
457     * (Render<T extends Entity) and this method has signature public void doRender(T entity, double d, double d1,
458     * double d2, float f, float f1). But JAD is pre 1.5 so doesn't do that.
459     */
460    public void doRender(Entity par1Entity, double par2, double par4, double par6, float par8, float par9)
461    {
462        this.doRenderLiving((EntityLiving)par1Entity, par2, par4, par6, par8, par9);
463    }
464}