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 }