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 }