    001package net.minecraft.client.particle;
    002
    003import cpw.mods.fml.relauncher.Side;
    004import cpw.mods.fml.relauncher.SideOnly;
    005import java.util.ArrayList;
    006import java.util.List;
    007import java.util.Random;
    008import net.minecraft.block.Block;
    009import net.minecraft.client.renderer.ActiveRenderInfo;
    010import net.minecraft.client.renderer.RenderEngine;
    011import net.minecraft.client.renderer.Tessellator;
    012import net.minecraft.entity.Entity;
    013import net.minecraft.util.MathHelper;
    014import net.minecraft.util.MovingObjectPosition;
    015import net.minecraft.world.World;
    016import org.lwjgl.opengl.GL11;
    017
    018@SideOnly(Side.CLIENT)
    019public class EffectRenderer
    020{
    021    /** Reference to the World object. */
    022    protected World worldObj;
    023    private List[] fxLayers = new List[4];
    024    private RenderEngine renderer;
    025
    026    /** RNG. */
    027    private Random rand = new Random();
    028
    029    public EffectRenderer(World par1World, RenderEngine par2RenderEngine)
    030    {
    031        if (par1World != null)
    032        {
    033            this.worldObj = par1World;
    034        }
    035
    036        this.renderer = par2RenderEngine;
    037
    038        for (int i = 0; i < 4; ++i)
    039        {
    040            this.fxLayers[i] = new ArrayList();
    041        }
    042    }
    043
    044    public void addEffect(EntityFX par1EntityFX)
    045    {
    046        int i = par1EntityFX.getFXLayer();
    047
    048        if (this.fxLayers[i].size() >= 4000)
    049        {
    050            this.fxLayers[i].remove(0);
    051        }
    052
    053        this.fxLayers[i].add(par1EntityFX);
    054    }
    055
    056    public void updateEffects()
    057    {
    058        for (int i = 0; i < 4; ++i)
    059        {
    060            for (int j = 0; j < this.fxLayers[i].size(); ++j)
    061            {
    062                EntityFX entityfx = (EntityFX)this.fxLayers[i].get(j);
    063
    064                if (entityfx != null)
    065                {
    066                    entityfx.onUpdate();
    067                }
    068
    069                if (entityfx == null || entityfx.isDead)
    070                {
    071                    this.fxLayers[i].remove(j--);
    072                }
    073            }
    074        }
    075    }
    076
    077    /**
    078     * Renders all current particles. Args player, partialTickTime
    079     */
    080    public void renderParticles(Entity par1Entity, float par2)
    081    {
    082        float f1 = ActiveRenderInfo.rotationX;
    083        float f2 = ActiveRenderInfo.rotationZ;
    084        float f3 = ActiveRenderInfo.rotationYZ;
    085        float f4 = ActiveRenderInfo.rotationXY;
    086        float f5 = ActiveRenderInfo.rotationXZ;
    087        EntityFX.interpPosX = par1Entity.lastTickPosX + (par1Entity.posX - par1Entity.lastTickPosX) * (double)par2;
    088        EntityFX.interpPosY = par1Entity.lastTickPosY + (par1Entity.posY - par1Entity.lastTickPosY) * (double)par2;
    089        EntityFX.interpPosZ = par1Entity.lastTickPosZ + (par1Entity.posZ - par1Entity.lastTickPosZ) * (double)par2;
    090
    091        for (int i = 0; i < 3; ++i)
    092        {
    093            if (!this.fxLayers[i].isEmpty())
    094            {
    095                switch (i)
    096                {
    097                    case 0:
    098                    default:
    099                        this.renderer.func_98187_b("/particles.png");
    100                        break;
    101                    case 1:
    102                        this.renderer.func_98187_b("/terrain.png");
    103                        break;
    104                    case 2:
    105                        this.renderer.func_98187_b("/gui/items.png");
    106                }
    107
    108                Tessellator tessellator = Tessellator.instance;
    109                GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
    110                GL11.glDepthMask(false);
    111                GL11.glEnable(GL11.GL_BLEND);
    112                GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
    113                GL11.glAlphaFunc(GL11.GL_GREATER, 0.003921569F);
    114                tessellator.startDrawingQuads();
    115
    116                for (int j = 0; j < this.fxLayers[i].size(); ++j)
    117                {
    118                    EntityFX entityfx = (EntityFX)this.fxLayers[i].get(j);
    119                    if (entityfx == null) continue;
    120                    tessellator.setBrightness(entityfx.getBrightnessForRender(par2));
    121                    entityfx.renderParticle(tessellator, par2, f1, f5, f2, f3, f4);
    122                }
    123
    124                tessellator.draw();
    125                GL11.glDisable(GL11.GL_BLEND);
    126                GL11.glDepthMask(true);
    127                GL11.glAlphaFunc(GL11.GL_GREATER, 0.1F);
    128            }
    129        }
    130    }
    131
    132    public void renderLitParticles(Entity par1Entity, float par2)
    133    {
    134        float f1 = MathHelper.cos(par1Entity.rotationYaw * 0.017453292F);
    135        float f2 = MathHelper.sin(par1Entity.rotationYaw * 0.017453292F);
    136        float f3 = -f2 * MathHelper.sin(par1Entity.rotationPitch * 0.017453292F);
    137        float f4 = f1 * MathHelper.sin(par1Entity.rotationPitch * 0.017453292F);
    138        float f5 = MathHelper.cos(par1Entity.rotationPitch * 0.017453292F);
    139        byte b0 = 3;
    140
    141        if (!this.fxLayers[b0].isEmpty())
    142        {
    143            Tessellator tessellator = Tessellator.instance;
    144
    145            for (int i = 0; i < this.fxLayers[b0].size(); ++i)
    146            {
    147                EntityFX entityfx = (EntityFX)this.fxLayers[b0].get(i);
    148                if (entityfx == null) continue;
    149                tessellator.setBrightness(entityfx.getBrightnessForRender(par2));
    150                entityfx.renderParticle(tessellator, par2, f1, f5, f2, f3, f4);
    151            }
    152        }
    153    }
    154
    155    public void clearEffects(World par1World)
    156    {
    157        this.worldObj = par1World;
    158
    159        for (int i = 0; i < 4; ++i)
    160        {
    161            this.fxLayers[i].clear();
    162        }
    163    }
    164
    165    public void addBlockDestroyEffects(int par1, int par2, int par3, int par4, int par5)
    166    {
    167        Block block = Block.blocksList[par4];
    168        if (block != null && !block.addBlockDestroyEffects(worldObj, par1, par2, par3, par5, this))
    169        {
    170            byte b0 = 4;
    171
    172            for (int j1 = 0; j1 < b0; ++j1)
    173            {
    174                for (int k1 = 0; k1 < b0; ++k1)
    175                {
    176                    for (int l1 = 0; l1 < b0; ++l1)
    177                    {
    178                        double d0 = (double)par1 + ((double)j1 + 0.5D) / (double)b0;
    179                        double d1 = (double)par2 + ((double)k1 + 0.5D) / (double)b0;
    180                        double d2 = (double)par3 + ((double)l1 + 0.5D) / (double)b0;
    181                        int i2 = this.rand.nextInt(6);
    182                        this.addEffect((new EntityDiggingFX(this.worldObj, d0, d1, d2, d0 - (double)par1 - 0.5D, d1 - (double)par2 - 0.5D, d2 - (double)par3 - 0.5D, block, i2, par5, this.renderer)).func_70596_a(par1, par2, par3));
    183                    }
    184                }
    185            }
    186        }
    187    }
    188
    189    /**
    190     * Adds block hit particles for the specified block. Args: x, y, z, sideHit
    191     */
    192    public void addBlockHitEffects(int par1, int par2, int par3, int par4)
    193    {
    194        int i1 = this.worldObj.getBlockId(par1, par2, par3);
    195
    196        if (i1 != 0)
    197        {
    198            Block block = Block.blocksList[i1];
    199            float f = 0.1F;
    200            double d0 = (double)par1 + this.rand.nextDouble() * (block.getBlockBoundsMaxX() - block.getBlockBoundsMinX() - (double)(f * 2.0F)) + (double)f + block.getBlockBoundsMinX();
    201            double d1 = (double)par2 + this.rand.nextDouble() * (block.getBlockBoundsMaxY() - block.getBlockBoundsMinY() - (double)(f * 2.0F)) + (double)f + block.getBlockBoundsMinY();
    202            double d2 = (double)par3 + this.rand.nextDouble() * (block.getBlockBoundsMaxZ() - block.getBlockBoundsMinZ() - (double)(f * 2.0F)) + (double)f + block.getBlockBoundsMinZ();
    203
    204            if (par4 == 0)
    205            {
    206                d1 = (double)par2 + block.getBlockBoundsMinY() - (double)f;
    207            }
    208
    209            if (par4 == 1)
    210            {
    211                d1 = (double)par2 + block.getBlockBoundsMaxY() + (double)f;
    212            }
    213
    214            if (par4 == 2)
    215            {
    216                d2 = (double)par3 + block.getBlockBoundsMinZ() - (double)f;
    217            }
    218
    219            if (par4 == 3)
    220            {
    221                d2 = (double)par3 + block.getBlockBoundsMaxZ() + (double)f;
    222            }
    223
    224            if (par4 == 4)
    225            {
    226                d0 = (double)par1 + block.getBlockBoundsMinX() - (double)f;
    227            }
    228
    229            if (par4 == 5)
    230            {
    231                d0 = (double)par1 + block.getBlockBoundsMaxX() + (double)f;
    232            }
    233
    234            this.addEffect((new EntityDiggingFX(this.worldObj, d0, d1, d2, 0.0D, 0.0D, 0.0D, block, par4, this.worldObj.getBlockMetadata(par1, par2, par3), this.renderer)).func_70596_a(par1, par2, par3).multiplyVelocity(0.2F).multipleParticleScaleBy(0.6F));
    235        }
    236    }
    237
    238    public String getStatistics()
    239    {
    240        return "" + (this.fxLayers[0].size() + this.fxLayers[1].size() + this.fxLayers[2].size());
    241    }
    242
    243    public void addBlockHitEffects(int x, int y, int z, MovingObjectPosition target)
    244    {
    245        Block block = Block.blocksList[worldObj.getBlockId(x, y, z)];
    246        if (block != null && !block.addBlockHitEffects(worldObj, target, this))
    247        {
    248            addBlockHitEffects(x, y, z, target.sideHit);
    249        }
    250     }
    251}