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.func_98187_b(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.func_98185_a();
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.func_94209_e();
109            float f8 = icon2.func_94206_g();
110            float f9 = icon2.func_94212_f();
111            float f10 = icon2.func_94210_h();
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.func_98187_b("%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 func_94143_a(IconRegister par1IconRegister) {}
361}