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}