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