001    package net.minecraft.client.renderer.entity;
002    
003    import cpw.mods.fml.relauncher.Side;
004    import cpw.mods.fml.relauncher.SideOnly;
005    import java.util.Random;
006    import net.minecraft.client.Minecraft;
007    import net.minecraft.client.gui.FontRenderer;
008    import net.minecraft.client.model.ModelBase;
009    import net.minecraft.client.model.ModelBox;
010    import net.minecraft.client.model.ModelRenderer;
011    import net.minecraft.client.renderer.OpenGlHelper;
012    import net.minecraft.client.renderer.RenderHelper;
013    import net.minecraft.client.renderer.Tessellator;
014    import net.minecraft.entity.Entity;
015    import net.minecraft.entity.EntityLiving;
016    import net.minecraft.entity.projectile.EntityArrow;
017    import net.minecraft.util.MathHelper;
018    import org.lwjgl.opengl.GL11;
019    import org.lwjgl.opengl.GL12;
020    
021    @SideOnly(Side.CLIENT)
022    public 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    }