001 package net.minecraft.src;
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 org.lwjgl.opengl.GL11;
008 import org.lwjgl.opengl.GL12;
009
010 @SideOnly(Side.CLIENT)
011 public class RenderLiving extends Render
012 {
013 protected ModelBase mainModel;
014
015 /** The model to be used during the render passes. */
016 protected ModelBase renderPassModel;
017
018 public RenderLiving(ModelBase par1ModelBase, float par2)
019 {
020 this.mainModel = par1ModelBase;
021 this.shadowSize = par2;
022 }
023
024 /**
025 * Sets the model to be used in the current render pass (the first render pass is done after the primary model is
026 * rendered) Args: model
027 */
028 public void setRenderPassModel(ModelBase par1ModelBase)
029 {
030 this.renderPassModel = par1ModelBase;
031 }
032
033 /**
034 * Returns a rotation angle that is inbetween two other rotation angles. par1 and par2 are the angles between which
035 * to interpolate, par3 is probably a float between 0.0 and 1.0 that tells us where "between" the two angles we are.
036 * Example: par1 = 30, par2 = 50, par3 = 0.5, then return = 40
037 */
038 private float interpolateRotation(float par1, float par2, float par3)
039 {
040 float var4;
041
042 for (var4 = par2 - par1; var4 < -180.0F; var4 += 360.0F)
043 {
044 ;
045 }
046
047 while (var4 >= 180.0F)
048 {
049 var4 -= 360.0F;
050 }
051
052 return par1 + par3 * var4;
053 }
054
055 public void doRenderLiving(EntityLiving par1EntityLiving, double par2, double par4, double par6, float par8, float par9)
056 {
057 GL11.glPushMatrix();
058 GL11.glDisable(GL11.GL_CULL_FACE);
059 this.mainModel.onGround = this.renderSwingProgress(par1EntityLiving, par9);
060
061 if (this.renderPassModel != null)
062 {
063 this.renderPassModel.onGround = this.mainModel.onGround;
064 }
065
066 this.mainModel.isRiding = par1EntityLiving.isRiding();
067
068 if (this.renderPassModel != null)
069 {
070 this.renderPassModel.isRiding = this.mainModel.isRiding;
071 }
072
073 this.mainModel.isChild = par1EntityLiving.isChild();
074
075 if (this.renderPassModel != null)
076 {
077 this.renderPassModel.isChild = this.mainModel.isChild;
078 }
079
080 try
081 {
082 float var10 = this.interpolateRotation(par1EntityLiving.prevRenderYawOffset, par1EntityLiving.renderYawOffset, par9);
083 float var11 = this.interpolateRotation(par1EntityLiving.prevRotationYawHead, par1EntityLiving.rotationYawHead, par9);
084 float var12 = par1EntityLiving.prevRotationPitch + (par1EntityLiving.rotationPitch - par1EntityLiving.prevRotationPitch) * par9;
085 this.renderLivingAt(par1EntityLiving, par2, par4, par6);
086 float var13 = this.handleRotationFloat(par1EntityLiving, par9);
087 this.rotateCorpse(par1EntityLiving, var13, var10, par9);
088 float var14 = 0.0625F;
089 GL11.glEnable(GL12.GL_RESCALE_NORMAL);
090 GL11.glScalef(-1.0F, -1.0F, 1.0F);
091 this.preRenderCallback(par1EntityLiving, par9);
092 GL11.glTranslatef(0.0F, -24.0F * var14 - 0.0078125F, 0.0F);
093 float var15 = par1EntityLiving.prevLegYaw + (par1EntityLiving.legYaw - par1EntityLiving.prevLegYaw) * par9;
094 float var16 = par1EntityLiving.legSwing - par1EntityLiving.legYaw * (1.0F - par9);
095
096 if (par1EntityLiving.isChild())
097 {
098 var16 *= 3.0F;
099 }
100
101 if (var15 > 1.0F)
102 {
103 var15 = 1.0F;
104 }
105
106 GL11.glEnable(GL11.GL_ALPHA_TEST);
107 this.mainModel.setLivingAnimations(par1EntityLiving, var16, var15, par9);
108 this.renderModel(par1EntityLiving, var16, var15, var13, var11 - var10, var12, var14);
109 float var19;
110 int var18;
111 float var20;
112 float var22;
113
114 for (int var17 = 0; var17 < 4; ++var17)
115 {
116 var18 = this.shouldRenderPass(par1EntityLiving, var17, par9);
117
118 if (var18 > 0)
119 {
120 this.renderPassModel.setLivingAnimations(par1EntityLiving, var16, var15, par9);
121 this.renderPassModel.render(par1EntityLiving, var16, var15, var13, var11 - var10, var12, var14);
122
123 if ((var18 & 240) == 16)
124 {
125 this.func_82408_c(par1EntityLiving, var17, par9);
126 this.renderPassModel.render(par1EntityLiving, var16, var15, var13, var11 - var10, var12, var14);
127 }
128
129 if ((var18 & 15) == 15)
130 {
131 var19 = (float)par1EntityLiving.ticksExisted + par9;
132 this.loadTexture("%blur%/misc/glint.png");
133 GL11.glEnable(GL11.GL_BLEND);
134 var20 = 0.5F;
135 GL11.glColor4f(var20, var20, var20, 1.0F);
136 GL11.glDepthFunc(GL11.GL_EQUAL);
137 GL11.glDepthMask(false);
138
139 for (int var21 = 0; var21 < 2; ++var21)
140 {
141 GL11.glDisable(GL11.GL_LIGHTING);
142 var22 = 0.76F;
143 GL11.glColor4f(0.5F * var22, 0.25F * var22, 0.8F * var22, 1.0F);
144 GL11.glBlendFunc(GL11.GL_SRC_COLOR, GL11.GL_ONE);
145 GL11.glMatrixMode(GL11.GL_TEXTURE);
146 GL11.glLoadIdentity();
147 float var23 = var19 * (0.001F + (float)var21 * 0.003F) * 20.0F;
148 float var24 = 0.33333334F;
149 GL11.glScalef(var24, var24, var24);
150 GL11.glRotatef(30.0F - (float)var21 * 60.0F, 0.0F, 0.0F, 1.0F);
151 GL11.glTranslatef(0.0F, var23, 0.0F);
152 GL11.glMatrixMode(GL11.GL_MODELVIEW);
153 this.renderPassModel.render(par1EntityLiving, var16, var15, var13, var11 - var10, var12, var14);
154 }
155
156 GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
157 GL11.glMatrixMode(GL11.GL_TEXTURE);
158 GL11.glDepthMask(true);
159 GL11.glLoadIdentity();
160 GL11.glMatrixMode(GL11.GL_MODELVIEW);
161 GL11.glEnable(GL11.GL_LIGHTING);
162 GL11.glDisable(GL11.GL_BLEND);
163 GL11.glDepthFunc(GL11.GL_LEQUAL);
164 }
165
166 GL11.glDisable(GL11.GL_BLEND);
167 GL11.glEnable(GL11.GL_ALPHA_TEST);
168 }
169 }
170
171 GL11.glDepthMask(true);
172 this.renderEquippedItems(par1EntityLiving, par9);
173 float var26 = par1EntityLiving.getBrightness(par9);
174 var18 = this.getColorMultiplier(par1EntityLiving, var26, par9);
175 OpenGlHelper.setActiveTexture(OpenGlHelper.lightmapTexUnit);
176 GL11.glDisable(GL11.GL_TEXTURE_2D);
177 OpenGlHelper.setActiveTexture(OpenGlHelper.defaultTexUnit);
178
179 if ((var18 >> 24 & 255) > 0 || par1EntityLiving.hurtTime > 0 || par1EntityLiving.deathTime > 0)
180 {
181 GL11.glDisable(GL11.GL_TEXTURE_2D);
182 GL11.glDisable(GL11.GL_ALPHA_TEST);
183 GL11.glEnable(GL11.GL_BLEND);
184 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
185 GL11.glDepthFunc(GL11.GL_EQUAL);
186
187 if (par1EntityLiving.hurtTime > 0 || par1EntityLiving.deathTime > 0)
188 {
189 GL11.glColor4f(var26, 0.0F, 0.0F, 0.4F);
190 this.mainModel.render(par1EntityLiving, var16, var15, var13, var11 - var10, var12, var14);
191
192 for (int var27 = 0; var27 < 4; ++var27)
193 {
194 if (this.inheritRenderPass(par1EntityLiving, var27, par9) >= 0)
195 {
196 GL11.glColor4f(var26, 0.0F, 0.0F, 0.4F);
197 this.renderPassModel.render(par1EntityLiving, var16, var15, var13, var11 - var10, var12, var14);
198 }
199 }
200 }
201
202 if ((var18 >> 24 & 255) > 0)
203 {
204 var19 = (float)(var18 >> 16 & 255) / 255.0F;
205 var20 = (float)(var18 >> 8 & 255) / 255.0F;
206 float var29 = (float)(var18 & 255) / 255.0F;
207 var22 = (float)(var18 >> 24 & 255) / 255.0F;
208 GL11.glColor4f(var19, var20, var29, var22);
209 this.mainModel.render(par1EntityLiving, var16, var15, var13, var11 - var10, var12, var14);
210
211 for (int var28 = 0; var28 < 4; ++var28)
212 {
213 if (this.inheritRenderPass(par1EntityLiving, var28, par9) >= 0)
214 {
215 GL11.glColor4f(var19, var20, var29, var22);
216 this.renderPassModel.render(par1EntityLiving, var16, var15, var13, var11 - var10, var12, var14);
217 }
218 }
219 }
220
221 GL11.glDepthFunc(GL11.GL_LEQUAL);
222 GL11.glDisable(GL11.GL_BLEND);
223 GL11.glEnable(GL11.GL_ALPHA_TEST);
224 GL11.glEnable(GL11.GL_TEXTURE_2D);
225 }
226
227 GL11.glDisable(GL12.GL_RESCALE_NORMAL);
228 }
229 catch (Exception var25)
230 {
231 var25.printStackTrace();
232 }
233
234 OpenGlHelper.setActiveTexture(OpenGlHelper.lightmapTexUnit);
235 GL11.glEnable(GL11.GL_TEXTURE_2D);
236 OpenGlHelper.setActiveTexture(OpenGlHelper.defaultTexUnit);
237 GL11.glEnable(GL11.GL_CULL_FACE);
238 GL11.glPopMatrix();
239 this.passSpecialRender(par1EntityLiving, par2, par4, par6);
240 }
241
242 /**
243 * Renders the model in RenderLiving
244 */
245 protected void renderModel(EntityLiving par1EntityLiving, float par2, float par3, float par4, float par5, float par6, float par7)
246 {
247 if (!par1EntityLiving.func_82150_aj())
248 {
249 this.loadDownloadableImageTexture(par1EntityLiving.skinUrl, par1EntityLiving.getTexture());
250 this.mainModel.render(par1EntityLiving, par2, par3, par4, par5, par6, par7);
251 }
252 else
253 {
254 this.mainModel.setRotationAngles(par2, par3, par4, par5, par6, par7, par1EntityLiving);
255 }
256 }
257
258 /**
259 * Sets a simple glTranslate on a LivingEntity.
260 */
261 protected void renderLivingAt(EntityLiving par1EntityLiving, double par2, double par4, double par6)
262 {
263 GL11.glTranslatef((float)par2, (float)par4, (float)par6);
264 }
265
266 protected void rotateCorpse(EntityLiving par1EntityLiving, float par2, float par3, float par4)
267 {
268 GL11.glRotatef(180.0F - par3, 0.0F, 1.0F, 0.0F);
269
270 if (par1EntityLiving.deathTime > 0)
271 {
272 float var5 = ((float)par1EntityLiving.deathTime + par4 - 1.0F) / 20.0F * 1.6F;
273 var5 = MathHelper.sqrt_float(var5);
274
275 if (var5 > 1.0F)
276 {
277 var5 = 1.0F;
278 }
279
280 GL11.glRotatef(var5 * this.getDeathMaxRotation(par1EntityLiving), 0.0F, 0.0F, 1.0F);
281 }
282 }
283
284 protected float renderSwingProgress(EntityLiving par1EntityLiving, float par2)
285 {
286 return par1EntityLiving.getSwingProgress(par2);
287 }
288
289 /**
290 * Defines what float the third param in setRotationAngles of ModelBase is
291 */
292 protected float handleRotationFloat(EntityLiving par1EntityLiving, float par2)
293 {
294 return (float)par1EntityLiving.ticksExisted + par2;
295 }
296
297 protected void renderEquippedItems(EntityLiving par1EntityLiving, float par2) {}
298
299 protected void func_85093_e(EntityLiving par1EntityLiving, float par2)
300 {
301 int var3 = par1EntityLiving.func_85035_bI();
302
303 if (var3 > 0)
304 {
305 EntityArrow var4 = new EntityArrow(par1EntityLiving.worldObj, par1EntityLiving.posX, par1EntityLiving.posY, par1EntityLiving.posZ);
306 Random var5 = new Random((long)par1EntityLiving.entityId);
307 RenderHelper.disableStandardItemLighting();
308
309 for (int var6 = 0; var6 < var3; ++var6)
310 {
311 GL11.glPushMatrix();
312 ModelRenderer var7 = this.mainModel.func_85181_a(var5);
313 ModelBox var8 = (ModelBox)var7.cubeList.get(var5.nextInt(var7.cubeList.size()));
314 var7.postRender(0.0625F);
315 float var9 = var5.nextFloat();
316 float var10 = var5.nextFloat();
317 float var11 = var5.nextFloat();
318 float var12 = (var8.posX1 + (var8.posX2 - var8.posX1) * var9) / 16.0F;
319 float var13 = (var8.posY1 + (var8.posY2 - var8.posY1) * var10) / 16.0F;
320 float var14 = (var8.posZ1 + (var8.posZ2 - var8.posZ1) * var11) / 16.0F;
321 GL11.glTranslatef(var12, var13, var14);
322 var9 = var9 * 2.0F - 1.0F;
323 var10 = var10 * 2.0F - 1.0F;
324 var11 = var11 * 2.0F - 1.0F;
325 var9 *= -1.0F;
326 var10 *= -1.0F;
327 var11 *= -1.0F;
328 float var15 = MathHelper.sqrt_float(var9 * var9 + var11 * var11);
329 var4.prevRotationYaw = var4.rotationYaw = (float)(Math.atan2((double)var9, (double)var11) * 180.0D / Math.PI);
330 var4.prevRotationPitch = var4.rotationPitch = (float)(Math.atan2((double)var10, (double)var15) * 180.0D / Math.PI);
331 double var16 = 0.0D;
332 double var18 = 0.0D;
333 double var20 = 0.0D;
334 float var22 = 0.0F;
335 this.renderManager.renderEntityWithPosYaw(var4, var16, var18, var20, var22, par2);
336 GL11.glPopMatrix();
337 }
338
339 RenderHelper.enableStandardItemLighting();
340 }
341 }
342
343 protected int inheritRenderPass(EntityLiving par1EntityLiving, int par2, float par3)
344 {
345 return this.shouldRenderPass(par1EntityLiving, par2, par3);
346 }
347
348 /**
349 * Queries whether should render the specified pass or not.
350 */
351 protected int shouldRenderPass(EntityLiving par1EntityLiving, int par2, float par3)
352 {
353 return -1;
354 }
355
356 protected void func_82408_c(EntityLiving par1EntityLiving, int par2, float par3) {}
357
358 protected float getDeathMaxRotation(EntityLiving par1EntityLiving)
359 {
360 return 90.0F;
361 }
362
363 /**
364 * Returns an ARGB int color back. Args: entityLiving, lightBrightness, partialTickTime
365 */
366 protected int getColorMultiplier(EntityLiving par1EntityLiving, float par2, float par3)
367 {
368 return 0;
369 }
370
371 /**
372 * Allows the render to do any OpenGL state modifications necessary before the model is rendered. Args:
373 * entityLiving, partialTickTime
374 */
375 protected void preRenderCallback(EntityLiving par1EntityLiving, float par2) {}
376
377 /**
378 * Passes the specialRender and renders it
379 */
380 protected void passSpecialRender(EntityLiving par1EntityLiving, double par2, double par4, double par6)
381 {
382 if (Minecraft.isDebugInfoEnabled())
383 {
384 ;
385 }
386 }
387
388 /**
389 * Draws the debug or playername text above a living
390 */
391 protected void renderLivingLabel(EntityLiving par1EntityLiving, String par2Str, double par3, double par5, double par7, int par9)
392 {
393 double var10 = par1EntityLiving.getDistanceSqToEntity(this.renderManager.livingPlayer);
394
395 if (var10 <= (double)(par9 * par9))
396 {
397 FontRenderer var12 = this.getFontRendererFromRenderManager();
398 float var13 = 1.6F;
399 float var14 = 0.016666668F * var13;
400 GL11.glPushMatrix();
401 GL11.glTranslatef((float)par3 + 0.0F, (float)par5 + 2.3F, (float)par7);
402 GL11.glNormal3f(0.0F, 1.0F, 0.0F);
403 GL11.glRotatef(-this.renderManager.playerViewY, 0.0F, 1.0F, 0.0F);
404 GL11.glRotatef(this.renderManager.playerViewX, 1.0F, 0.0F, 0.0F);
405 GL11.glScalef(-var14, -var14, var14);
406 GL11.glDisable(GL11.GL_LIGHTING);
407 GL11.glDepthMask(false);
408 GL11.glDisable(GL11.GL_DEPTH_TEST);
409 GL11.glEnable(GL11.GL_BLEND);
410 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
411 Tessellator var15 = Tessellator.instance;
412 byte var16 = 0;
413
414 if (par2Str.equals("deadmau5"))
415 {
416 var16 = -10;
417 }
418
419 GL11.glDisable(GL11.GL_TEXTURE_2D);
420 var15.startDrawingQuads();
421 int var17 = var12.getStringWidth(par2Str) / 2;
422 var15.setColorRGBA_F(0.0F, 0.0F, 0.0F, 0.25F);
423 var15.addVertex((double)(-var17 - 1), (double)(-1 + var16), 0.0D);
424 var15.addVertex((double)(-var17 - 1), (double)(8 + var16), 0.0D);
425 var15.addVertex((double)(var17 + 1), (double)(8 + var16), 0.0D);
426 var15.addVertex((double)(var17 + 1), (double)(-1 + var16), 0.0D);
427 var15.draw();
428 GL11.glEnable(GL11.GL_TEXTURE_2D);
429 var12.drawString(par2Str, -var12.getStringWidth(par2Str) / 2, var16, 553648127);
430 GL11.glEnable(GL11.GL_DEPTH_TEST);
431 GL11.glDepthMask(true);
432 var12.drawString(par2Str, -var12.getStringWidth(par2Str) / 2, var16, -1);
433 GL11.glEnable(GL11.GL_LIGHTING);
434 GL11.glDisable(GL11.GL_BLEND);
435 GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
436 GL11.glPopMatrix();
437 }
438 }
439
440 /**
441 * Actually renders the given argument. This is a synthetic bridge method, always casting down its argument and then
442 * handing it off to a worker function which does the actual work. In all probabilty, the class Render is generic
443 * (Render<T extends Entity) and this method has signature public void doRender(T entity, double d, double d1,
444 * double d2, float f, float f1). But JAD is pre 1.5 so doesn't do that.
445 */
446 public void doRender(Entity par1Entity, double par2, double par4, double par6, float par8, float par9)
447 {
448 this.doRenderLiving((EntityLiving)par1Entity, par2, par4, par6, par8, par9);
449 }
450 }