001 package net.minecraft.client.renderer.entity;
002
003 import cpw.mods.fml.common.Side;
004 import cpw.mods.fml.common.asm.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 protected void func_85093_e(EntityLiving par1EntityLiving, float par2)
311 {
312 int var3 = par1EntityLiving.func_85035_bI();
313
314 if (var3 > 0)
315 {
316 EntityArrow var4 = new EntityArrow(par1EntityLiving.worldObj, par1EntityLiving.posX, par1EntityLiving.posY, par1EntityLiving.posZ);
317 Random var5 = new Random((long)par1EntityLiving.entityId);
318 RenderHelper.disableStandardItemLighting();
319
320 for (int var6 = 0; var6 < var3; ++var6)
321 {
322 GL11.glPushMatrix();
323 ModelRenderer var7 = this.mainModel.func_85181_a(var5);
324 ModelBox var8 = (ModelBox)var7.cubeList.get(var5.nextInt(var7.cubeList.size()));
325 var7.postRender(0.0625F);
326 float var9 = var5.nextFloat();
327 float var10 = var5.nextFloat();
328 float var11 = var5.nextFloat();
329 float var12 = (var8.posX1 + (var8.posX2 - var8.posX1) * var9) / 16.0F;
330 float var13 = (var8.posY1 + (var8.posY2 - var8.posY1) * var10) / 16.0F;
331 float var14 = (var8.posZ1 + (var8.posZ2 - var8.posZ1) * var11) / 16.0F;
332 GL11.glTranslatef(var12, var13, var14);
333 var9 = var9 * 2.0F - 1.0F;
334 var10 = var10 * 2.0F - 1.0F;
335 var11 = var11 * 2.0F - 1.0F;
336 var9 *= -1.0F;
337 var10 *= -1.0F;
338 var11 *= -1.0F;
339 float var15 = MathHelper.sqrt_float(var9 * var9 + var11 * var11);
340 var4.prevRotationYaw = var4.rotationYaw = (float)(Math.atan2((double)var9, (double)var11) * 180.0D / Math.PI);
341 var4.prevRotationPitch = var4.rotationPitch = (float)(Math.atan2((double)var10, (double)var15) * 180.0D / Math.PI);
342 double var16 = 0.0D;
343 double var18 = 0.0D;
344 double var20 = 0.0D;
345 float var22 = 0.0F;
346 this.renderManager.renderEntityWithPosYaw(var4, var16, var18, var20, var22, par2);
347 GL11.glPopMatrix();
348 }
349
350 RenderHelper.enableStandardItemLighting();
351 }
352 }
353
354 protected int inheritRenderPass(EntityLiving par1EntityLiving, int par2, float par3)
355 {
356 return this.shouldRenderPass(par1EntityLiving, par2, par3);
357 }
358
359 /**
360 * Queries whether should render the specified pass or not.
361 */
362 protected int shouldRenderPass(EntityLiving par1EntityLiving, int par2, float par3)
363 {
364 return -1;
365 }
366
367 protected void func_82408_c(EntityLiving par1EntityLiving, int par2, float par3) {}
368
369 protected float getDeathMaxRotation(EntityLiving par1EntityLiving)
370 {
371 return 90.0F;
372 }
373
374 /**
375 * Returns an ARGB int color back. Args: entityLiving, lightBrightness, partialTickTime
376 */
377 protected int getColorMultiplier(EntityLiving par1EntityLiving, float par2, float par3)
378 {
379 return 0;
380 }
381
382 /**
383 * Allows the render to do any OpenGL state modifications necessary before the model is rendered. Args:
384 * entityLiving, partialTickTime
385 */
386 protected void preRenderCallback(EntityLiving par1EntityLiving, float par2) {}
387
388 /**
389 * Passes the specialRender and renders it
390 */
391 protected void passSpecialRender(EntityLiving par1EntityLiving, double par2, double par4, double par6)
392 {
393 if (Minecraft.isDebugInfoEnabled())
394 {
395 ;
396 }
397 }
398
399 /**
400 * Draws the debug or playername text above a living
401 */
402 protected void renderLivingLabel(EntityLiving par1EntityLiving, String par2Str, double par3, double par5, double par7, int par9)
403 {
404 double var10 = par1EntityLiving.getDistanceSqToEntity(this.renderManager.livingPlayer);
405
406 if (var10 <= (double)(par9 * par9))
407 {
408 FontRenderer var12 = this.getFontRendererFromRenderManager();
409 float var13 = 1.6F;
410 float var14 = 0.016666668F * var13;
411 GL11.glPushMatrix();
412 GL11.glTranslatef((float)par3 + 0.0F, (float)par5 + 2.3F, (float)par7);
413 GL11.glNormal3f(0.0F, 1.0F, 0.0F);
414 GL11.glRotatef(-this.renderManager.playerViewY, 0.0F, 1.0F, 0.0F);
415 GL11.glRotatef(this.renderManager.playerViewX, 1.0F, 0.0F, 0.0F);
416 GL11.glScalef(-var14, -var14, var14);
417 GL11.glDisable(GL11.GL_LIGHTING);
418 GL11.glDepthMask(false);
419 GL11.glDisable(GL11.GL_DEPTH_TEST);
420 GL11.glEnable(GL11.GL_BLEND);
421 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
422 Tessellator var15 = Tessellator.instance;
423 byte var16 = 0;
424
425 if (par2Str.equals("deadmau5"))
426 {
427 var16 = -10;
428 }
429
430 GL11.glDisable(GL11.GL_TEXTURE_2D);
431 var15.startDrawingQuads();
432 int var17 = var12.getStringWidth(par2Str) / 2;
433 var15.setColorRGBA_F(0.0F, 0.0F, 0.0F, 0.25F);
434 var15.addVertex((double)(-var17 - 1), (double)(-1 + var16), 0.0D);
435 var15.addVertex((double)(-var17 - 1), (double)(8 + var16), 0.0D);
436 var15.addVertex((double)(var17 + 1), (double)(8 + var16), 0.0D);
437 var15.addVertex((double)(var17 + 1), (double)(-1 + var16), 0.0D);
438 var15.draw();
439 GL11.glEnable(GL11.GL_TEXTURE_2D);
440 var12.drawString(par2Str, -var12.getStringWidth(par2Str) / 2, var16, 553648127);
441 GL11.glEnable(GL11.GL_DEPTH_TEST);
442 GL11.glDepthMask(true);
443 var12.drawString(par2Str, -var12.getStringWidth(par2Str) / 2, var16, -1);
444 GL11.glEnable(GL11.GL_LIGHTING);
445 GL11.glDisable(GL11.GL_BLEND);
446 GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
447 GL11.glPopMatrix();
448 }
449 }
450
451 /**
452 * Actually renders the given argument. This is a synthetic bridge method, always casting down its argument and then
453 * handing it off to a worker function which does the actual work. In all probabilty, the class Render is generic
454 * (Render<T extends Entity) and this method has signature public void doRender(T entity, double d, double d1,
455 * double d2, float f, float f1). But JAD is pre 1.5 so doesn't do that.
456 */
457 public void doRender(Entity par1Entity, double par2, double par4, double par6, float par8, float par9)
458 {
459 this.doRenderLiving((EntityLiving)par1Entity, par2, par4, par6, par8, par9);
460 }
461 }