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