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 }