    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    }