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 == 15)
123 {
124 var19 = (float)par1EntityLiving.ticksExisted + par9;
125 this.loadTexture("%blur%/misc/glint.png");
126 GL11.glEnable(GL11.GL_BLEND);
127 var20 = 0.5F;
128 GL11.glColor4f(var20, var20, var20, 1.0F);
129 GL11.glDepthFunc(GL11.GL_EQUAL);
130 GL11.glDepthMask(false);
131
132 for (int var21 = 0; var21 < 2; ++var21)
133 {
134 GL11.glDisable(GL11.GL_LIGHTING);
135 var22 = 0.76F;
136 GL11.glColor4f(0.5F * var22, 0.25F * var22, 0.8F * var22, 1.0F);
137 GL11.glBlendFunc(GL11.GL_SRC_COLOR, GL11.GL_ONE);
138 GL11.glMatrixMode(GL11.GL_TEXTURE);
139 GL11.glLoadIdentity();
140 float var23 = var19 * (0.001F + (float)var21 * 0.003F) * 20.0F;
141 float var24 = 0.33333334F;
142 GL11.glScalef(var24, var24, var24);
143 GL11.glRotatef(30.0F - (float)var21 * 60.0F, 0.0F, 0.0F, 1.0F);
144 GL11.glTranslatef(0.0F, var23, 0.0F);
145 GL11.glMatrixMode(GL11.GL_MODELVIEW);
146 this.renderPassModel.render(par1EntityLiving, var16, var15, var13, var11 - var10, var12, var14);
147 }
148
149 GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
150 GL11.glMatrixMode(GL11.GL_TEXTURE);
151 GL11.glDepthMask(true);
152 GL11.glLoadIdentity();
153 GL11.glMatrixMode(GL11.GL_MODELVIEW);
154 GL11.glEnable(GL11.GL_LIGHTING);
155 GL11.glDisable(GL11.GL_BLEND);
156 GL11.glDepthFunc(GL11.GL_LEQUAL);
157 }
158
159 GL11.glDisable(GL11.GL_BLEND);
160 GL11.glEnable(GL11.GL_ALPHA_TEST);
161 }
162 }
163
164 this.renderEquippedItems(par1EntityLiving, par9);
165 float var26 = par1EntityLiving.getBrightness(par9);
166 var18 = this.getColorMultiplier(par1EntityLiving, var26, par9);
167 OpenGlHelper.setActiveTexture(OpenGlHelper.lightmapTexUnit);
168 GL11.glDisable(GL11.GL_TEXTURE_2D);
169 OpenGlHelper.setActiveTexture(OpenGlHelper.defaultTexUnit);
170
171 if ((var18 >> 24 & 255) > 0 || par1EntityLiving.hurtTime > 0 || par1EntityLiving.deathTime > 0)
172 {
173 GL11.glDisable(GL11.GL_TEXTURE_2D);
174 GL11.glDisable(GL11.GL_ALPHA_TEST);
175 GL11.glEnable(GL11.GL_BLEND);
176 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
177 GL11.glDepthFunc(GL11.GL_EQUAL);
178
179 if (par1EntityLiving.hurtTime > 0 || par1EntityLiving.deathTime > 0)
180 {
181 GL11.glColor4f(var26, 0.0F, 0.0F, 0.4F);
182 this.mainModel.render(par1EntityLiving, var16, var15, var13, var11 - var10, var12, var14);
183
184 for (int var27 = 0; var27 < 4; ++var27)
185 {
186 if (this.inheritRenderPass(par1EntityLiving, var27, par9) >= 0)
187 {
188 GL11.glColor4f(var26, 0.0F, 0.0F, 0.4F);
189 this.renderPassModel.render(par1EntityLiving, var16, var15, var13, var11 - var10, var12, var14);
190 }
191 }
192 }
193
194 if ((var18 >> 24 & 255) > 0)
195 {
196 var19 = (float)(var18 >> 16 & 255) / 255.0F;
197 var20 = (float)(var18 >> 8 & 255) / 255.0F;
198 float var29 = (float)(var18 & 255) / 255.0F;
199 var22 = (float)(var18 >> 24 & 255) / 255.0F;
200 GL11.glColor4f(var19, var20, var29, var22);
201 this.mainModel.render(par1EntityLiving, var16, var15, var13, var11 - var10, var12, var14);
202
203 for (int var28 = 0; var28 < 4; ++var28)
204 {
205 if (this.inheritRenderPass(par1EntityLiving, var28, par9) >= 0)
206 {
207 GL11.glColor4f(var19, var20, var29, var22);
208 this.renderPassModel.render(par1EntityLiving, var16, var15, var13, var11 - var10, var12, var14);
209 }
210 }
211 }
212
213 GL11.glDepthFunc(GL11.GL_LEQUAL);
214 GL11.glDisable(GL11.GL_BLEND);
215 GL11.glEnable(GL11.GL_ALPHA_TEST);
216 GL11.glEnable(GL11.GL_TEXTURE_2D);
217 }
218
219 GL11.glDisable(GL12.GL_RESCALE_NORMAL);
220 }
221 catch (Exception var25)
222 {
223 var25.printStackTrace();
224 }
225
226 OpenGlHelper.setActiveTexture(OpenGlHelper.lightmapTexUnit);
227 GL11.glEnable(GL11.GL_TEXTURE_2D);
228 OpenGlHelper.setActiveTexture(OpenGlHelper.defaultTexUnit);
229 GL11.glEnable(GL11.GL_CULL_FACE);
230 GL11.glPopMatrix();
231 this.passSpecialRender(par1EntityLiving, par2, par4, par6);
232 }
233
234 /**
235 * Renders the model in RenderLiving
236 */
237 protected void renderModel(EntityLiving par1EntityLiving, float par2, float par3, float par4, float par5, float par6, float par7)
238 {
239 this.loadDownloadableImageTexture(par1EntityLiving.skinUrl, par1EntityLiving.getTexture());
240 this.mainModel.render(par1EntityLiving, par2, par3, par4, par5, par6, par7);
241 }
242
243 /**
244 * Sets a simple glTranslate on a LivingEntity.
245 */
246 protected void renderLivingAt(EntityLiving par1EntityLiving, double par2, double par4, double par6)
247 {
248 GL11.glTranslatef((float)par2, (float)par4, (float)par6);
249 }
250
251 protected void rotateCorpse(EntityLiving par1EntityLiving, float par2, float par3, float par4)
252 {
253 GL11.glRotatef(180.0F - par3, 0.0F, 1.0F, 0.0F);
254
255 if (par1EntityLiving.deathTime > 0)
256 {
257 float var5 = ((float)par1EntityLiving.deathTime + par4 - 1.0F) / 20.0F * 1.6F;
258 var5 = MathHelper.sqrt_float(var5);
259
260 if (var5 > 1.0F)
261 {
262 var5 = 1.0F;
263 }
264
265 GL11.glRotatef(var5 * this.getDeathMaxRotation(par1EntityLiving), 0.0F, 0.0F, 1.0F);
266 }
267 }
268
269 protected float renderSwingProgress(EntityLiving par1EntityLiving, float par2)
270 {
271 return par1EntityLiving.getSwingProgress(par2);
272 }
273
274 /**
275 * Defines what float the third param in setRotationAngles of ModelBase is
276 */
277 protected float handleRotationFloat(EntityLiving par1EntityLiving, float par2)
278 {
279 return (float)par1EntityLiving.ticksExisted + par2;
280 }
281
282 protected void renderEquippedItems(EntityLiving par1EntityLiving, float par2) {}
283
284 protected int inheritRenderPass(EntityLiving par1EntityLiving, int par2, float par3)
285 {
286 return this.shouldRenderPass(par1EntityLiving, par2, par3);
287 }
288
289 /**
290 * Queries whether should render the specified pass or not.
291 */
292 protected int shouldRenderPass(EntityLiving par1EntityLiving, int par2, float par3)
293 {
294 return -1;
295 }
296
297 protected float getDeathMaxRotation(EntityLiving par1EntityLiving)
298 {
299 return 90.0F;
300 }
301
302 /**
303 * Returns an ARGB int color back. Args: entityLiving, lightBrightness, partialTickTime
304 */
305 protected int getColorMultiplier(EntityLiving par1EntityLiving, float par2, float par3)
306 {
307 return 0;
308 }
309
310 /**
311 * Allows the render to do any OpenGL state modifications necessary before the model is rendered. Args:
312 * entityLiving, partialTickTime
313 */
314 protected void preRenderCallback(EntityLiving par1EntityLiving, float par2) {}
315
316 /**
317 * Passes the specialRender and renders it
318 */
319 protected void passSpecialRender(EntityLiving par1EntityLiving, double par2, double par4, double par6)
320 {
321 if (Minecraft.isDebugInfoEnabled())
322 {
323 ;
324 }
325 }
326
327 /**
328 * Draws the debug or playername text above a living
329 */
330 protected void renderLivingLabel(EntityLiving par1EntityLiving, String par2Str, double par3, double par5, double par7, int par9)
331 {
332 double var10 = par1EntityLiving.getDistanceSqToEntity(this.renderManager.livingPlayer);
333
334 if (var10 <= (double)(par9 * par9))
335 {
336 FontRenderer var12 = this.getFontRendererFromRenderManager();
337 float var13 = 1.6F;
338 float var14 = 0.016666668F * var13;
339 GL11.glPushMatrix();
340 GL11.glTranslatef((float)par3 + 0.0F, (float)par5 + 2.3F, (float)par7);
341 GL11.glNormal3f(0.0F, 1.0F, 0.0F);
342 GL11.glRotatef(-this.renderManager.playerViewY, 0.0F, 1.0F, 0.0F);
343 GL11.glRotatef(this.renderManager.playerViewX, 1.0F, 0.0F, 0.0F);
344 GL11.glScalef(-var14, -var14, var14);
345 GL11.glDisable(GL11.GL_LIGHTING);
346 GL11.glDepthMask(false);
347 GL11.glDisable(GL11.GL_DEPTH_TEST);
348 GL11.glEnable(GL11.GL_BLEND);
349 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
350 Tessellator var15 = Tessellator.instance;
351 byte var16 = 0;
352
353 if (par2Str.equals("deadmau5"))
354 {
355 var16 = -10;
356 }
357
358 GL11.glDisable(GL11.GL_TEXTURE_2D);
359 var15.startDrawingQuads();
360 int var17 = var12.getStringWidth(par2Str) / 2;
361 var15.setColorRGBA_F(0.0F, 0.0F, 0.0F, 0.25F);
362 var15.addVertex((double)(-var17 - 1), (double)(-1 + var16), 0.0D);
363 var15.addVertex((double)(-var17 - 1), (double)(8 + var16), 0.0D);
364 var15.addVertex((double)(var17 + 1), (double)(8 + var16), 0.0D);
365 var15.addVertex((double)(var17 + 1), (double)(-1 + var16), 0.0D);
366 var15.draw();
367 GL11.glEnable(GL11.GL_TEXTURE_2D);
368 var12.drawString(par2Str, -var12.getStringWidth(par2Str) / 2, var16, 553648127);
369 GL11.glEnable(GL11.GL_DEPTH_TEST);
370 GL11.glDepthMask(true);
371 var12.drawString(par2Str, -var12.getStringWidth(par2Str) / 2, var16, -1);
372 GL11.glEnable(GL11.GL_LIGHTING);
373 GL11.glDisable(GL11.GL_BLEND);
374 GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
375 GL11.glPopMatrix();
376 }
377 }
378
379 /**
380 * Actually renders the given argument. This is a synthetic bridge method, always casting down its argument and then
381 * handing it off to a worker function which does the actual work. In all probabilty, the class Render is generic
382 * (Render<T extends Entity) and this method has signature public void doRender(T entity, double d, double d1,
383 * double d2, float f, float f1). But JAD is pre 1.5 so doesn't do that.
384 */
385 public void doRender(Entity par1Entity, double par2, double par4, double par6, float par8, float par9)
386 {
387 this.doRenderLiving((EntityLiving)par1Entity, par2, par4, par6, par8, par9);
388 }
389 }