    001package net.minecraft.client.renderer.entity;
    002
    003import cpw.mods.fml.relauncher.Side;
    004import cpw.mods.fml.relauncher.SideOnly;
    005import net.minecraft.block.Block;
    006import net.minecraft.client.gui.FontRenderer;
    007import net.minecraft.client.model.ModelBase;
    008import net.minecraft.client.model.ModelBiped;
    009import net.minecraft.client.renderer.RenderBlocks;
    010import net.minecraft.client.renderer.RenderEngine;
    011import net.minecraft.client.renderer.Tessellator;
    012import net.minecraft.client.renderer.texture.IconRegister;
    013import net.minecraft.entity.Entity;
    014import net.minecraft.entity.EntityLiving;
    015import net.minecraft.util.AxisAlignedBB;
    016import net.minecraft.util.Icon;
    017import net.minecraft.util.MathHelper;
    018import net.minecraft.world.World;
    019import org.lwjgl.opengl.GL11;
    020
    021@SideOnly(Side.CLIENT)
    022public abstract class Render
    023{
    024    protected RenderManager renderManager;
    025    private ModelBase modelBase = new ModelBiped();
    026    protected RenderBlocks renderBlocks = new RenderBlocks();
    027    protected float shadowSize = 0.0F;
    028
    029    /**
    030     * Determines the darkness of the object's shadow. Higher value makes a darker shadow.
    031     */
    032    protected float shadowOpaque = 1.0F;
    033
    034    /**
    035     * Actually renders the given argument. This is a synthetic bridge method, always casting down its argument and then
    036     * handing it off to a worker function which does the actual work. In all probabilty, the class Render is generic
    037     * (Render<T extends Entity) and this method has signature public void doRender(T entity, double d, double d1,
    038     * double d2, float f, float f1). But JAD is pre 1.5 so doesn't do that.
    039     */
    040    public abstract void doRender(Entity entity, double d0, double d1, double d2, float f, float f1);
    041
    042    /**
    043     * loads the specified texture
    044     */
    045    protected void loadTexture(String par1Str)
    046    {
    047        this.renderManager.renderEngine.bindTexture(par1Str);
    048    }
    049
    050    /**
    051     * loads the specified downloadable texture or alternative built in texture
    052     */
    053    protected boolean loadDownloadableImageTexture(String par1Str, String par2Str)
    054    {
    055        RenderEngine renderengine = this.renderManager.renderEngine;
    056        int i = renderengine.getTextureForDownloadableImage(par1Str, par2Str);
    057
    058        if (i >= 0)
    059        {
    060            GL11.glBindTexture(GL11.GL_TEXTURE_2D, i);
    061            renderengine.resetBoundTexture();
    062            return true;
    063        }
    064        else
    065        {
    066            return false;
    067        }
    068    }
    069
    070    /**
    071     * Renders fire on top of the entity. Args: entity, x, y, z, partialTickTime
    072     */
    073    private void renderEntityOnFire(Entity par1Entity, double par2, double par4, double par6, float par8)
    074    {
    075        GL11.glDisable(GL11.GL_LIGHTING);
    076        Icon icon = Block.fire.func_94438_c(0);
    077        Icon icon1 = Block.fire.func_94438_c(1);
    078        GL11.glPushMatrix();
    079        GL11.glTranslatef((float)par2, (float)par4, (float)par6);
    080        float f1 = par1Entity.width * 1.4F;
    081        GL11.glScalef(f1, f1, f1);
    082        this.loadTexture("/terrain.png");
    083        Tessellator tessellator = Tessellator.instance;
    084        float f2 = 0.5F;
    085        float f3 = 0.0F;
    086        float f4 = par1Entity.height / f1;
    087        float f5 = (float)(par1Entity.posY - par1Entity.boundingBox.minY);
    088        GL11.glRotatef(-this.renderManager.playerViewY, 0.0F, 1.0F, 0.0F);
    089        GL11.glTranslatef(0.0F, 0.0F, -0.3F + (float)((int)f4) * 0.02F);
    090        GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
    091        float f6 = 0.0F;
    092        int i = 0;
    093        tessellator.startDrawingQuads();
    094
    095        while (f4 > 0.0F)
    096        {
    097            Icon icon2;
    098
    099            if (i % 2 == 0)
    100            {
    101                icon2 = icon;
    102            }
    103            else
    104            {
    105                icon2 = icon1;
    106            }
    107
    108            float f7 = icon2.getMinU();
    109            float f8 = icon2.getMinV();
    110            float f9 = icon2.getMaxU();
    111            float f10 = icon2.getMaxV();
    112
    113            if (i / 2 % 2 == 0)
    114            {
    115                float f11 = f9;
    116                f9 = f7;
    117                f7 = f11;
    118            }
    119
    120            tessellator.addVertexWithUV((double)(f2 - f3), (double)(0.0F - f5), (double)f6, (double)f9, (double)f10);
    121            tessellator.addVertexWithUV((double)(-f2 - f3), (double)(0.0F - f5), (double)f6, (double)f7, (double)f10);
    122            tessellator.addVertexWithUV((double)(-f2 - f3), (double)(1.4F - f5), (double)f6, (double)f7, (double)f8);
    123            tessellator.addVertexWithUV((double)(f2 - f3), (double)(1.4F - f5), (double)f6, (double)f9, (double)f8);
    124            f4 -= 0.45F;
    125            f5 -= 0.45F;
    126            f2 *= 0.9F;
    127            f6 += 0.03F;
    128            ++i;
    129        }
    130
    131        tessellator.draw();
    132        GL11.glPopMatrix();
    133        GL11.glEnable(GL11.GL_LIGHTING);
    134    }
    135
    136    /**
    137     * Renders the entity shadows at the position, shadow alpha and partialTickTime. Args: entity, x, y, z, shadowAlpha,
    138     * partialTickTime
    139     */
    140    private void renderShadow(Entity par1Entity, double par2, double par4, double par6, float par8, float par9)
    141    {
    142        GL11.glEnable(GL11.GL_BLEND);
    143        GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
    144        this.renderManager.renderEngine.bindTexture("%clamp%/misc/shadow.png");
    145        World world = this.getWorldFromRenderManager();
    146        GL11.glDepthMask(false);
    147        float f2 = this.shadowSize;
    148
    149        if (par1Entity instanceof EntityLiving)
    150        {
    151            EntityLiving entityliving = (EntityLiving)par1Entity;
    152            f2 *= entityliving.getRenderSizeModifier();
    153
    154            if (entityliving.isChild())
    155            {
    156                f2 *= 0.5F;
    157            }
    158        }
    159
    160        double d3 = par1Entity.lastTickPosX + (par1Entity.posX - par1Entity.lastTickPosX) * (double)par9;
    161        double d4 = par1Entity.lastTickPosY + (par1Entity.posY - par1Entity.lastTickPosY) * (double)par9 + (double)par1Entity.getShadowSize();
    162        double d5 = par1Entity.lastTickPosZ + (par1Entity.posZ - par1Entity.lastTickPosZ) * (double)par9;
    163        int i = MathHelper.floor_double(d3 - (double)f2);
    164        int j = MathHelper.floor_double(d3 + (double)f2);
    165        int k = MathHelper.floor_double(d4 - (double)f2);
    166        int l = MathHelper.floor_double(d4);
    167        int i1 = MathHelper.floor_double(d5 - (double)f2);
    168        int j1 = MathHelper.floor_double(d5 + (double)f2);
    169        double d6 = par2 - d3;
    170        double d7 = par4 - d4;
    171        double d8 = par6 - d5;
    172        Tessellator tessellator = Tessellator.instance;
    173        tessellator.startDrawingQuads();
    174
    175        for (int k1 = i; k1 <= j; ++k1)
    176        {
    177            for (int l1 = k; l1 <= l; ++l1)
    178            {
    179                for (int i2 = i1; i2 <= j1; ++i2)
    180                {
    181                    int j2 = world.getBlockId(k1, l1 - 1, i2);
    182
    183                    if (j2 > 0 && world.getBlockLightValue(k1, l1, i2) > 3)
    184                    {
    185                        this.renderShadowOnBlock(Block.blocksList[j2], par2, par4 + (double)par1Entity.getShadowSize(), par6, k1, l1, i2, par8, f2, d6, d7 + (double)par1Entity.getShadowSize(), d8);
    186                    }
    187                }
    188            }
    189        }
    190
    191        tessellator.draw();
    192        GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
    193        GL11.glDisable(GL11.GL_BLEND);
    194        GL11.glDepthMask(true);
    195    }
    196
    197    /**
    198     * Returns the render manager's world object
    199     */
    200    private World getWorldFromRenderManager()
    201    {
    202        return this.renderManager.worldObj;
    203    }
    204
    205    /**
    206     * Renders a shadow projected down onto the specified block. Brightness of the block plus how far away on the Y axis
    207     * determines the alpha of the shadow.  Args: block, centerX, centerY, centerZ, blockX, blockY, blockZ, baseAlpha,
    208     * shadowSize, xOffset, yOffset, zOffset
    209     */
    210    private void renderShadowOnBlock(Block par1Block, double par2, double par4, double par6, int par8, int par9, int par10, float par11, float par12, double par13, double par15, double par17)
    211    {
    212        Tessellator tessellator = Tessellator.instance;
    213
    214        if (par1Block.renderAsNormalBlock())
    215        {
    216            double d6 = ((double)par11 - (par4 - ((double)par9 + par15)) / 2.0D) * 0.5D * (double)this.getWorldFromRenderManager().getLightBrightness(par8, par9, par10);
    217
    218            if (d6 >= 0.0D)
    219            {
    220                if (d6 > 1.0D)
    221                {
    222                    d6 = 1.0D;
    223                }
    224
    225                tessellator.setColorRGBA_F(1.0F, 1.0F, 1.0F, (float)d6);
    226                double d7 = (double)par8 + par1Block.getBlockBoundsMinX() + par13;
    227                double d8 = (double)par8 + par1Block.getBlockBoundsMaxX() + par13;
    228                double d9 = (double)par9 + par1Block.getBlockBoundsMinY() + par15 + 0.015625D;
    229                double d10 = (double)par10 + par1Block.getBlockBoundsMinZ() + par17;
    230                double d11 = (double)par10 + par1Block.getBlockBoundsMaxZ() + par17;
    231                float f2 = (float)((par2 - d7) / 2.0D / (double)par12 + 0.5D);
    232                float f3 = (float)((par2 - d8) / 2.0D / (double)par12 + 0.5D);
    233                float f4 = (float)((par6 - d10) / 2.0D / (double)par12 + 0.5D);
    234                float f5 = (float)((par6 - d11) / 2.0D / (double)par12 + 0.5D);
    235                tessellator.addVertexWithUV(d7, d9, d10, (double)f2, (double)f4);
    236                tessellator.addVertexWithUV(d7, d9, d11, (double)f2, (double)f5);
    237                tessellator.addVertexWithUV(d8, d9, d11, (double)f3, (double)f5);
    238                tessellator.addVertexWithUV(d8, d9, d10, (double)f3, (double)f4);
    239            }
    240        }
    241    }
    242
    243    /**
    244     * Renders a white box with the bounds of the AABB translated by the offset. Args: aabb, x, y, z
    245     */
    246    public static void renderOffsetAABB(AxisAlignedBB par0AxisAlignedBB, double par1, double par3, double par5)
    247    {
    248        GL11.glDisable(GL11.GL_TEXTURE_2D);
    249        Tessellator tessellator = Tessellator.instance;
    250        GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
    251        tessellator.startDrawingQuads();
    252        tessellator.setTranslation(par1, par3, par5);
    253        tessellator.setNormal(0.0F, 0.0F, -1.0F);
    254        tessellator.addVertex(par0AxisAlignedBB.minX, par0AxisAlignedBB.maxY, par0AxisAlignedBB.minZ);
    255        tessellator.addVertex(par0AxisAlignedBB.maxX, par0AxisAlignedBB.maxY, par0AxisAlignedBB.minZ);
    256        tessellator.addVertex(par0AxisAlignedBB.maxX, par0AxisAlignedBB.minY, par0AxisAlignedBB.minZ);
    257        tessellator.addVertex(par0AxisAlignedBB.minX, par0AxisAlignedBB.minY, par0AxisAlignedBB.minZ);
    258        tessellator.setNormal(0.0F, 0.0F, 1.0F);
    259        tessellator.addVertex(par0AxisAlignedBB.minX, par0AxisAlignedBB.minY, par0AxisAlignedBB.maxZ);
    260        tessellator.addVertex(par0AxisAlignedBB.maxX, par0AxisAlignedBB.minY, par0AxisAlignedBB.maxZ);
    261        tessellator.addVertex(par0AxisAlignedBB.maxX, par0AxisAlignedBB.maxY, par0AxisAlignedBB.maxZ);
    262        tessellator.addVertex(par0AxisAlignedBB.minX, par0AxisAlignedBB.maxY, par0AxisAlignedBB.maxZ);
    263        tessellator.setNormal(0.0F, -1.0F, 0.0F);
    264        tessellator.addVertex(par0AxisAlignedBB.minX, par0AxisAlignedBB.minY, par0AxisAlignedBB.minZ);
    265        tessellator.addVertex(par0AxisAlignedBB.maxX, par0AxisAlignedBB.minY, par0AxisAlignedBB.minZ);
    266        tessellator.addVertex(par0AxisAlignedBB.maxX, par0AxisAlignedBB.minY, par0AxisAlignedBB.maxZ);
    267        tessellator.addVertex(par0AxisAlignedBB.minX, par0AxisAlignedBB.minY, par0AxisAlignedBB.maxZ);
    268        tessellator.setNormal(0.0F, 1.0F, 0.0F);
    269        tessellator.addVertex(par0AxisAlignedBB.minX, par0AxisAlignedBB.maxY, par0AxisAlignedBB.maxZ);
    270        tessellator.addVertex(par0AxisAlignedBB.maxX, par0AxisAlignedBB.maxY, par0AxisAlignedBB.maxZ);
    271        tessellator.addVertex(par0AxisAlignedBB.maxX, par0AxisAlignedBB.maxY, par0AxisAlignedBB.minZ);
    272        tessellator.addVertex(par0AxisAlignedBB.minX, par0AxisAlignedBB.maxY, par0AxisAlignedBB.minZ);
    273        tessellator.setNormal(-1.0F, 0.0F, 0.0F);
    274        tessellator.addVertex(par0AxisAlignedBB.minX, par0AxisAlignedBB.minY, par0AxisAlignedBB.maxZ);
    275        tessellator.addVertex(par0AxisAlignedBB.minX, par0AxisAlignedBB.maxY, par0AxisAlignedBB.maxZ);
    276        tessellator.addVertex(par0AxisAlignedBB.minX, par0AxisAlignedBB.maxY, par0AxisAlignedBB.minZ);
    277        tessellator.addVertex(par0AxisAlignedBB.minX, par0AxisAlignedBB.minY, par0AxisAlignedBB.minZ);
    278        tessellator.setNormal(1.0F, 0.0F, 0.0F);
    279        tessellator.addVertex(par0AxisAlignedBB.maxX, par0AxisAlignedBB.minY, par0AxisAlignedBB.minZ);
    280        tessellator.addVertex(par0AxisAlignedBB.maxX, par0AxisAlignedBB.maxY, par0AxisAlignedBB.minZ);
    281        tessellator.addVertex(par0AxisAlignedBB.maxX, par0AxisAlignedBB.maxY, par0AxisAlignedBB.maxZ);
    282        tessellator.addVertex(par0AxisAlignedBB.maxX, par0AxisAlignedBB.minY, par0AxisAlignedBB.maxZ);
    283        tessellator.setTranslation(0.0D, 0.0D, 0.0D);
    284        tessellator.draw();
    285        GL11.glEnable(GL11.GL_TEXTURE_2D);
    286    }
    287
    288    /**
    289     * Adds to the tesselator a box using the aabb for the bounds. Args: aabb
    290     */
    291    public static void renderAABB(AxisAlignedBB par0AxisAlignedBB)
    292    {
    293        Tessellator tessellator = Tessellator.instance;
    294        tessellator.startDrawingQuads();
    295        tessellator.addVertex(par0AxisAlignedBB.minX, par0AxisAlignedBB.maxY, par0AxisAlignedBB.minZ);
    296        tessellator.addVertex(par0AxisAlignedBB.maxX, par0AxisAlignedBB.maxY, par0AxisAlignedBB.minZ);
    297        tessellator.addVertex(par0AxisAlignedBB.maxX, par0AxisAlignedBB.minY, par0AxisAlignedBB.minZ);
    298        tessellator.addVertex(par0AxisAlignedBB.minX, par0AxisAlignedBB.minY, par0AxisAlignedBB.minZ);
    299        tessellator.addVertex(par0AxisAlignedBB.minX, par0AxisAlignedBB.minY, par0AxisAlignedBB.maxZ);
    300        tessellator.addVertex(par0AxisAlignedBB.maxX, par0AxisAlignedBB.minY, par0AxisAlignedBB.maxZ);
    301        tessellator.addVertex(par0AxisAlignedBB.maxX, par0AxisAlignedBB.maxY, par0AxisAlignedBB.maxZ);
    302        tessellator.addVertex(par0AxisAlignedBB.minX, par0AxisAlignedBB.maxY, par0AxisAlignedBB.maxZ);
    303        tessellator.addVertex(par0AxisAlignedBB.minX, par0AxisAlignedBB.minY, par0AxisAlignedBB.minZ);
    304        tessellator.addVertex(par0AxisAlignedBB.maxX, par0AxisAlignedBB.minY, par0AxisAlignedBB.minZ);
    305        tessellator.addVertex(par0AxisAlignedBB.maxX, par0AxisAlignedBB.minY, par0AxisAlignedBB.maxZ);
    306        tessellator.addVertex(par0AxisAlignedBB.minX, par0AxisAlignedBB.minY, par0AxisAlignedBB.maxZ);
    307        tessellator.addVertex(par0AxisAlignedBB.minX, par0AxisAlignedBB.maxY, par0AxisAlignedBB.maxZ);
    308        tessellator.addVertex(par0AxisAlignedBB.maxX, par0AxisAlignedBB.maxY, par0AxisAlignedBB.maxZ);
    309        tessellator.addVertex(par0AxisAlignedBB.maxX, par0AxisAlignedBB.maxY, par0AxisAlignedBB.minZ);
    310        tessellator.addVertex(par0AxisAlignedBB.minX, par0AxisAlignedBB.maxY, par0AxisAlignedBB.minZ);
    311        tessellator.addVertex(par0AxisAlignedBB.minX, par0AxisAlignedBB.minY, par0AxisAlignedBB.maxZ);
    312        tessellator.addVertex(par0AxisAlignedBB.minX, par0AxisAlignedBB.maxY, par0AxisAlignedBB.maxZ);
    313        tessellator.addVertex(par0AxisAlignedBB.minX, par0AxisAlignedBB.maxY, par0AxisAlignedBB.minZ);
    314        tessellator.addVertex(par0AxisAlignedBB.minX, par0AxisAlignedBB.minY, par0AxisAlignedBB.minZ);
    315        tessellator.addVertex(par0AxisAlignedBB.maxX, par0AxisAlignedBB.minY, par0AxisAlignedBB.minZ);
    316        tessellator.addVertex(par0AxisAlignedBB.maxX, par0AxisAlignedBB.maxY, par0AxisAlignedBB.minZ);
    317        tessellator.addVertex(par0AxisAlignedBB.maxX, par0AxisAlignedBB.maxY, par0AxisAlignedBB.maxZ);
    318        tessellator.addVertex(par0AxisAlignedBB.maxX, par0AxisAlignedBB.minY, par0AxisAlignedBB.maxZ);
    319        tessellator.draw();
    320    }
    321
    322    /**
    323     * Sets the RenderManager.
    324     */
    325    public void setRenderManager(RenderManager par1RenderManager)
    326    {
    327        this.renderManager = par1RenderManager;
    328    }
    329
    330    /**
    331     * Renders the entity's shadow and fire (if its on fire). Args: entity, x, y, z, yaw, partialTickTime
    332     */
    333    public void doRenderShadowAndFire(Entity par1Entity, double par2, double par4, double par6, float par8, float par9)
    334    {
    335        if (this.renderManager.options.fancyGraphics && this.shadowSize > 0.0F && !par1Entity.getHasActivePotion())
    336        {
    337            double d3 = this.renderManager.getDistanceToCamera(par1Entity.posX, par1Entity.posY, par1Entity.posZ);
    338            float f2 = (float)((1.0D - d3 / 256.0D) * (double)this.shadowOpaque);
    339
    340            if (f2 > 0.0F)
    341            {
    342                this.renderShadow(par1Entity, par2, par4, par6, f2, par9);
    343            }
    344        }
    345
    346        if (par1Entity.canRenderOnFire())
    347        {
    348            this.renderEntityOnFire(par1Entity, par2, par4, par6, par9);
    349        }
    350    }
    351
    352    /**
    353     * Returns the font renderer from the set render manager
    354     */
    355    public FontRenderer getFontRendererFromRenderManager()
    356    {
    357        return this.renderManager.getFontRenderer();
    358    }
    359
    360    public void updateIcons(IconRegister par1IconRegister) {}
    361}