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