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.ArrayList;
006 import java.util.Iterator;
007 import java.util.List;
008 import java.util.Map.Entry;
009 import java.util.Random;
010
011 import net.minecraftforge.client.ForgeHooksClient;
012 import net.minecraftforge.common.ForgeHooks;
013
014 import org.lwjgl.opengl.GL11;
015
016 import com.google.common.collect.ArrayListMultimap;
017 import com.google.common.collect.Multimap;
018
019 @SideOnly(Side.CLIENT)
020 public class EffectRenderer
021 {
022 /** Reference to the World object. */
023 protected World worldObj;
024 private List[] fxLayers = new List[4];
025 private List field_90038_c = new ArrayList();
026 private RenderEngine renderer;
027
028 /** RNG. */
029 private Random rand = new Random();
030
031 private Multimap<String, EntityFX> effectList = ArrayListMultimap.create();
032
033 public EffectRenderer(World par1World, RenderEngine par2RenderEngine)
034 {
035 if (par1World != null)
036 {
037 this.worldObj = par1World;
038 }
039
040 this.renderer = par2RenderEngine;
041
042 for (int var3 = 0; var3 < 4; ++var3)
043 {
044 this.fxLayers[var3] = new ArrayList();
045 }
046 }
047
048 public void addEffect(EntityFX par1EntityFX)
049 {
050 this.field_90038_c.add(par1EntityFX);
051 }
052
053 private void func_90037_b(EntityFX par1EntityFX)
054 {
055 int var2 = par1EntityFX.getFXLayer();
056
057 if (this.fxLayers[var2].size() >= 4000)
058 {
059 this.fxLayers[var2].remove(0);
060 }
061
062 this.fxLayers[var2].add(par1EntityFX);
063 }
064
065 public void updateEffects()
066 {
067 for (int var1 = 0; var1 < 4; ++var1)
068 {
069 EntityFX var2 = null;
070
071 try
072 {
073 for (int var3 = 0; var3 < this.fxLayers[var1].size(); ++var3)
074 {
075 var2 = (EntityFX)this.fxLayers[var1].get(var3);
076
077 if (var2 != null)
078 {
079 var2.onUpdate();
080 }
081
082 if (var2 == null || var2.isDead)
083 {
084 this.fxLayers[var1].remove(var3--);
085 }
086 }
087 }
088 catch (Throwable var7)
089 {
090 CrashReport var4 = CrashReport.func_85055_a(var7, "Uncaught exception while ticking particles");
091 CrashReportCategory var5 = var4.func_85058_a("Particle engine details");
092 var5.addCrashSectionCallable("Last ticked particle", new CallableLastTickedParticle(this, var2));
093 var5.addCrashSection("Texture index", Integer.valueOf(var1));
094 throw new ReportedException(var4);
095 }
096 }
097
098 Iterator<Entry<String, EntityFX>> itr = effectList.entries().iterator();
099 while (itr.hasNext())
100 {
101 EntityFX fx = itr.next().getValue();
102 fx.onUpdate();
103 if (fx.isDead)
104 {
105 itr.remove();
106 }
107 }
108
109 Iterator var8 = this.field_90038_c.iterator();
110
111 while (var8.hasNext())
112 {
113 this.func_90037_b((EntityFX)var8.next());
114 }
115
116 this.field_90038_c.clear();
117 }
118
119 /**
120 * Renders all current particles. Args player, partialTickTime
121 */
122 public void renderParticles(Entity par1Entity, float par2)
123 {
124 float var3 = ActiveRenderInfo.rotationX;
125 float var4 = ActiveRenderInfo.rotationZ;
126 float var5 = ActiveRenderInfo.rotationYZ;
127 float var6 = ActiveRenderInfo.rotationXY;
128 float var7 = ActiveRenderInfo.rotationXZ;
129 EntityFX.interpPosX = par1Entity.lastTickPosX + (par1Entity.posX - par1Entity.lastTickPosX) * (double)par2;
130 EntityFX.interpPosY = par1Entity.lastTickPosY + (par1Entity.posY - par1Entity.lastTickPosY) * (double)par2;
131 EntityFX.interpPosZ = par1Entity.lastTickPosZ + (par1Entity.posZ - par1Entity.lastTickPosZ) * (double)par2;
132
133 for (int var8 = 0; var8 < 3; ++var8)
134 {
135 if (!this.fxLayers[var8].isEmpty())
136 {
137 int var9 = 0;
138
139 if (var8 == 0)
140 {
141 var9 = this.renderer.getTexture("/particles.png");
142 }
143
144 if (var8 == 1)
145 {
146 var9 = this.renderer.getTexture("/terrain.png");
147 }
148
149 if (var8 == 2)
150 {
151 var9 = this.renderer.getTexture("/gui/items.png");
152 }
153
154 GL11.glBindTexture(GL11.GL_TEXTURE_2D, var9);
155 Tessellator var10 = Tessellator.instance;
156 GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
157 GL11.glEnable(GL11.GL_BLEND);
158 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
159 var10.startDrawingQuads();
160
161 for (int var11 = 0; var11 < this.fxLayers[var8].size(); ++var11)
162 {
163 EntityFX var12 = (EntityFX)this.fxLayers[var8].get(var11);
164 if (var12 == null) continue;
165 var10.setBrightness(var12.getBrightnessForRender(par2));
166 var12.renderParticle(var10, par2, var3, var7, var4, var5, var6);
167 }
168
169 var10.draw();
170 GL11.glDisable(GL11.GL_BLEND);
171 }
172 }
173
174 for (String key : effectList.keySet())
175 {
176 ForgeHooksClient.bindTexture(key, 0);
177 for (EntityFX entry : effectList.get(key))
178 {
179 if (entry == null) continue;
180 Tessellator tessallator = Tessellator.instance;
181 //GL11.glBindTexture(GL11.GL_TEXTURE_2D, renderer.getTexture(key));
182 tessallator.startDrawingQuads();
183
184 if (entry.getFXLayer() != 3)
185 {
186 tessallator.setBrightness(entry.getBrightnessForRender(par2));
187 entry.renderParticle(tessallator, par2, var3, var7, var4, var5, var6);
188 }
189
190 tessallator.draw();
191 }
192 ForgeHooksClient.unbindTexture();
193 }
194 }
195
196 public void renderLitParticles(Entity par1Entity, float par2)
197 {
198 float var4 = MathHelper.cos(par1Entity.rotationYaw * 0.017453292F);
199 float var5 = MathHelper.sin(par1Entity.rotationYaw * 0.017453292F);
200 float var6 = -var5 * MathHelper.sin(par1Entity.rotationPitch * 0.017453292F);
201 float var7 = var4 * MathHelper.sin(par1Entity.rotationPitch * 0.017453292F);
202 float var8 = MathHelper.cos(par1Entity.rotationPitch * 0.017453292F);
203 byte var9 = 3;
204
205 if (!this.fxLayers[var9].isEmpty())
206 {
207 Tessellator var10 = Tessellator.instance;
208
209 for (int var11 = 0; var11 < this.fxLayers[var9].size(); ++var11)
210 {
211 EntityFX var12 = (EntityFX)this.fxLayers[var9].get(var11);
212 if (var12 == null) continue;
213 var10.setBrightness(var12.getBrightnessForRender(par2));
214 var12.renderParticle(var10, par2, var4, var8, var5, var6, var7);
215 }
216 }
217 }
218
219 public void clearEffects(World par1World)
220 {
221 this.worldObj = par1World;
222
223 for (int var2 = 0; var2 < 4; ++var2)
224 {
225 this.fxLayers[var2].clear();
226 }
227
228 effectList.clear();
229 }
230
231 public void addBlockDestroyEffects(int par1, int par2, int par3, int par4, int par5)
232 {
233 Block var6 = Block.blocksList[par4];
234 if (var6 != null && !var6.addBlockDestroyEffects(worldObj, par1, par2, par3, par5, this))
235 {
236 byte var7 = 4;
237
238 for (int var8 = 0; var8 < var7; ++var8)
239 {
240 for (int var9 = 0; var9 < var7; ++var9)
241 {
242 for (int var10 = 0; var10 < var7; ++var10)
243 {
244 double var11 = (double)par1 + ((double)var8 + 0.5D) / (double)var7;
245 double var13 = (double)par2 + ((double)var9 + 0.5D) / (double)var7;
246 double var15 = (double)par3 + ((double)var10 + 0.5D) / (double)var7;
247 int var17 = this.rand.nextInt(6);
248 this.addEffect((new EntityDiggingFX(this.worldObj, var11, var13, var15, var11 - (double)par1 - 0.5D, var13 - (double)par2 - 0.5D, var15 - (double)par3 - 0.5D, var6, var17, par5)).func_70596_a(par1, par2, par3), var6);
249 }
250 }
251 }
252 }
253 }
254
255 /**
256 * Adds block hit particles for the specified block. Args: x, y, z, sideHit
257 */
258 public void addBlockHitEffects(int par1, int par2, int par3, int par4)
259 {
260 int var5 = this.worldObj.getBlockId(par1, par2, par3);
261
262 if (var5 != 0)
263 {
264 Block var6 = Block.blocksList[var5];
265 float var7 = 0.1F;
266 double var8 = (double)par1 + this.rand.nextDouble() * (var6.getBlockBoundsMaxX() - var6.getBlockBoundsMinX() - (double)(var7 * 2.0F)) + (double)var7 + var6.getBlockBoundsMinX();
267 double var10 = (double)par2 + this.rand.nextDouble() * (var6.getBlockBoundsMaxY() - var6.getBlockBoundsMinY() - (double)(var7 * 2.0F)) + (double)var7 + var6.getBlockBoundsMinY();
268 double var12 = (double)par3 + this.rand.nextDouble() * (var6.getBlockBoundsMaxZ() - var6.getBlockBoundsMinZ() - (double)(var7 * 2.0F)) + (double)var7 + var6.getBlockBoundsMinZ();
269
270 if (par4 == 0)
271 {
272 var10 = (double)par2 + var6.getBlockBoundsMinY() - (double)var7;
273 }
274
275 if (par4 == 1)
276 {
277 var10 = (double)par2 + var6.getBlockBoundsMaxY() + (double)var7;
278 }
279
280 if (par4 == 2)
281 {
282 var12 = (double)par3 + var6.getBlockBoundsMinZ() - (double)var7;
283 }
284
285 if (par4 == 3)
286 {
287 var12 = (double)par3 + var6.getBlockBoundsMaxZ() + (double)var7;
288 }
289
290 if (par4 == 4)
291 {
292 var8 = (double)par1 + var6.getBlockBoundsMinX() - (double)var7;
293 }
294
295 if (par4 == 5)
296 {
297 var8 = (double)par1 + var6.getBlockBoundsMaxX() + (double)var7;
298 }
299
300 this.addEffect((new EntityDiggingFX(this.worldObj, var8, var10, var12, 0.0D, 0.0D, 0.0D, var6, par4, this.worldObj.getBlockMetadata(par1, par2, par3))).func_70596_a(par1, par2, par3).multiplyVelocity(0.2F).multipleParticleScaleBy(0.6F), var6);
301 }
302 }
303
304 public String getStatistics()
305 {
306 int size = 0;
307 for (List x : fxLayers)
308 {
309 size += x.size();
310 }
311 size += effectList.size();
312 return Integer.toString(size);
313 }
314
315 public void addEffect(EntityFX effect, Object obj)
316 {
317 if (obj == null || !(obj instanceof Block || obj instanceof Item))
318 {
319 addEffect(effect);
320 return;
321 }
322
323 if (obj instanceof Item && ((Item)obj).isDefaultTexture)
324 {
325 addEffect(effect);
326 return;
327 }
328
329 if (obj instanceof Block && ((Block)obj).isDefaultTexture)
330 {
331 addEffect(effect);
332 return;
333 }
334
335 String texture = "/terrain.png";
336 if (effect.getFXLayer() == 0)
337 {
338 texture = "/particles.png";
339 }
340 else if (effect.getFXLayer() == 2)
341 {
342 texture = "/gui/items.png";
343 }
344 texture = ForgeHooks.getTexture(texture, obj);
345 effectList.put(texture, effect);
346 }
347
348 public void addBlockHitEffects(int x, int y, int z, MovingObjectPosition target)
349 {
350 Block block = Block.blocksList[worldObj.getBlockId(x, y, z)];
351 if (block != null && !block.addBlockHitEffects(worldObj, target, this))
352 {
353 addBlockHitEffects(x, y, z, target.sideHit);
354 }
355 }
356 }