    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}