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    }