    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    }