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 RenderEngine renderer; 026 027 /** RNG. */ 028 private Random rand = new Random(); 029 030 private Multimap<String, EntityFX> effectList = ArrayListMultimap.create(); 031 032 public EffectRenderer(World par1World, RenderEngine par2RenderEngine) 033 { 034 if (par1World != null) 035 { 036 this.worldObj = par1World; 037 } 038 039 this.renderer = par2RenderEngine; 040 041 for (int var3 = 0; var3 < 4; ++var3) 042 { 043 this.fxLayers[var3] = new ArrayList(); 044 } 045 } 046 047 public void addEffect(EntityFX par1EntityFX) 048 { 049 int var2 = par1EntityFX.getFXLayer(); 050 051 if (this.fxLayers[var2].size() >= 4000) 052 { 053 this.fxLayers[var2].remove(0); 054 } 055 056 this.fxLayers[var2].add(par1EntityFX); 057 } 058 059 public void updateEffects() 060 { 061 for (int var1 = 0; var1 < 4; ++var1) 062 { 063 EntityFX var2 = null; 064 065 try 066 { 067 for (int var3 = 0; var3 < this.fxLayers[var1].size(); ++var3) 068 { 069 var2 = (EntityFX)this.fxLayers[var1].get(var3); 070 071 if (var2 != null) 072 { 073 var2.onUpdate(); 074 } 075 076 if (var2 == null || var2.isDead) 077 { 078 this.fxLayers[var1].remove(var3--); 079 } 080 } 081 } 082 catch (Throwable var7) 083 { 084 CrashReport var4 = CrashReport.func_85055_a(var7, "Uncaught exception while ticking particles"); 085 CrashReportCategory var5 = var4.func_85058_a("Particle engine details"); 086 var5.addCrashSectionCallable("Last ticked particle", new CallableLastTickedParticle(this, var2)); 087 var5.addCrashSection("Texture index", Integer.valueOf(var1)); 088 throw new ReportedException(var4); 089 } 090 } 091 092 Iterator<Entry<String, EntityFX>> itr = effectList.entries().iterator(); 093 while (itr.hasNext()) 094 { 095 EntityFX fx = itr.next().getValue(); 096 fx.onUpdate(); 097 if (fx.isDead) 098 { 099 itr.remove(); 100 } 101 } 102 } 103 104 /** 105 * Renders all current particles. Args player, partialTickTime 106 */ 107 public void renderParticles(Entity par1Entity, float par2) 108 { 109 float var3 = ActiveRenderInfo.rotationX; 110 float var4 = ActiveRenderInfo.rotationZ; 111 float var5 = ActiveRenderInfo.rotationYZ; 112 float var6 = ActiveRenderInfo.rotationXY; 113 float var7 = ActiveRenderInfo.rotationXZ; 114 EntityFX.interpPosX = par1Entity.lastTickPosX + (par1Entity.posX - par1Entity.lastTickPosX) * (double)par2; 115 EntityFX.interpPosY = par1Entity.lastTickPosY + (par1Entity.posY - par1Entity.lastTickPosY) * (double)par2; 116 EntityFX.interpPosZ = par1Entity.lastTickPosZ + (par1Entity.posZ - par1Entity.lastTickPosZ) * (double)par2; 117 118 for (int var8 = 0; var8 < 3; ++var8) 119 { 120 if (!this.fxLayers[var8].isEmpty()) 121 { 122 int var9 = 0; 123 124 if (var8 == 0) 125 { 126 var9 = this.renderer.getTexture("/particles.png"); 127 } 128 129 if (var8 == 1) 130 { 131 var9 = this.renderer.getTexture("/terrain.png"); 132 } 133 134 if (var8 == 2) 135 { 136 var9 = this.renderer.getTexture("/gui/items.png"); 137 } 138 139 GL11.glBindTexture(GL11.GL_TEXTURE_2D, var9); 140 Tessellator var10 = Tessellator.instance; 141 GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); 142 GL11.glEnable(GL11.GL_BLEND); 143 GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); 144 var10.startDrawingQuads(); 145 146 for (int var11 = 0; var11 < this.fxLayers[var8].size(); ++var11) 147 { 148 EntityFX var12 = (EntityFX)this.fxLayers[var8].get(var11); 149 if (var12 == null) continue; 150 var10.setBrightness(var12.getBrightnessForRender(par2)); 151 var12.renderParticle(var10, par2, var3, var7, var4, var5, var6); 152 } 153 154 var10.draw(); 155 GL11.glDisable(GL11.GL_BLEND); 156 } 157 } 158 159 for (String key : effectList.keySet()) 160 { 161 ForgeHooksClient.bindTexture(key, 0); 162 for (EntityFX entry : effectList.get(key)) 163 { 164 if (entry == null) continue; 165 Tessellator tessallator = Tessellator.instance; 166 //GL11.glBindTexture(GL11.GL_TEXTURE_2D, renderer.getTexture(key)); 167 tessallator.startDrawingQuads(); 168 169 if (entry.getFXLayer() != 3) 170 { 171 tessallator.setBrightness(entry.getBrightnessForRender(par2)); 172 entry.renderParticle(tessallator, par2, var3, var7, var4, var5, var6); 173 } 174 175 tessallator.draw(); 176 } 177 ForgeHooksClient.unbindTexture(); 178 } 179 } 180 181 public void renderLitParticles(Entity par1Entity, float par2) 182 { 183 float var4 = MathHelper.cos(par1Entity.rotationYaw * 0.017453292F); 184 float var5 = MathHelper.sin(par1Entity.rotationYaw * 0.017453292F); 185 float var6 = -var5 * MathHelper.sin(par1Entity.rotationPitch * 0.017453292F); 186 float var7 = var4 * MathHelper.sin(par1Entity.rotationPitch * 0.017453292F); 187 float var8 = MathHelper.cos(par1Entity.rotationPitch * 0.017453292F); 188 byte var9 = 3; 189 190 if (!this.fxLayers[var9].isEmpty()) 191 { 192 Tessellator var10 = Tessellator.instance; 193 194 for (int var11 = 0; var11 < this.fxLayers[var9].size(); ++var11) 195 { 196 EntityFX var12 = (EntityFX)this.fxLayers[var9].get(var11); 197 if (var12 == null) continue; 198 var10.setBrightness(var12.getBrightnessForRender(par2)); 199 var12.renderParticle(var10, par2, var4, var8, var5, var6, var7); 200 } 201 } 202 } 203 204 public void clearEffects(World par1World) 205 { 206 this.worldObj = par1World; 207 208 for (int var2 = 0; var2 < 4; ++var2) 209 { 210 this.fxLayers[var2].clear(); 211 } 212 213 effectList.clear(); 214 } 215 216 public void addBlockDestroyEffects(int par1, int par2, int par3, int par4, int par5) 217 { 218 Block var6 = Block.blocksList[par4]; 219 if (var6 != null && !var6.addBlockDestroyEffects(worldObj, par1, par2, par3, par5, this)) 220 { 221 byte var7 = 4; 222 223 for (int var8 = 0; var8 < var7; ++var8) 224 { 225 for (int var9 = 0; var9 < var7; ++var9) 226 { 227 for (int var10 = 0; var10 < var7; ++var10) 228 { 229 double var11 = (double)par1 + ((double)var8 + 0.5D) / (double)var7; 230 double var13 = (double)par2 + ((double)var9 + 0.5D) / (double)var7; 231 double var15 = (double)par3 + ((double)var10 + 0.5D) / (double)var7; 232 int var17 = this.rand.nextInt(6); 233 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); 234 } 235 } 236 } 237 } 238 } 239 240 /** 241 * Adds block hit particles for the specified block. Args: x, y, z, sideHit 242 */ 243 public void addBlockHitEffects(int par1, int par2, int par3, int par4) 244 { 245 int var5 = this.worldObj.getBlockId(par1, par2, par3); 246 247 if (var5 != 0) 248 { 249 Block var6 = Block.blocksList[var5]; 250 float var7 = 0.1F; 251 double var8 = (double)par1 + this.rand.nextDouble() * (var6.getBlockBoundsMaxX() - var6.getBlockBoundsMinX() - (double)(var7 * 2.0F)) + (double)var7 + var6.getBlockBoundsMinX(); 252 double var10 = (double)par2 + this.rand.nextDouble() * (var6.getBlockBoundsMaxY() - var6.getBlockBoundsMinY() - (double)(var7 * 2.0F)) + (double)var7 + var6.getBlockBoundsMinY(); 253 double var12 = (double)par3 + this.rand.nextDouble() * (var6.getBlockBoundsMaxZ() - var6.getBlockBoundsMinZ() - (double)(var7 * 2.0F)) + (double)var7 + var6.getBlockBoundsMinZ(); 254 255 if (par4 == 0) 256 { 257 var10 = (double)par2 + var6.getBlockBoundsMinY() - (double)var7; 258 } 259 260 if (par4 == 1) 261 { 262 var10 = (double)par2 + var6.getBlockBoundsMaxY() + (double)var7; 263 } 264 265 if (par4 == 2) 266 { 267 var12 = (double)par3 + var6.getBlockBoundsMinZ() - (double)var7; 268 } 269 270 if (par4 == 3) 271 { 272 var12 = (double)par3 + var6.getBlockBoundsMaxZ() + (double)var7; 273 } 274 275 if (par4 == 4) 276 { 277 var8 = (double)par1 + var6.getBlockBoundsMinX() - (double)var7; 278 } 279 280 if (par4 == 5) 281 { 282 var8 = (double)par1 + var6.getBlockBoundsMaxX() + (double)var7; 283 } 284 285 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); 286 } 287 } 288 289 public String getStatistics() 290 { 291 int size = 0; 292 for (List x : fxLayers) 293 { 294 size += x.size(); 295 } 296 size += effectList.size(); 297 return Integer.toString(size); 298 } 299 300 public void addEffect(EntityFX effect, Object obj) 301 { 302 if (obj == null || !(obj instanceof Block || obj instanceof Item)) 303 { 304 addEffect(effect); 305 return; 306 } 307 308 if (obj instanceof Item && ((Item)obj).isDefaultTexture) 309 { 310 addEffect(effect); 311 return; 312 } 313 314 if (obj instanceof Block && ((Block)obj).isDefaultTexture) 315 { 316 addEffect(effect); 317 return; 318 } 319 320 String texture = "/terrain.png"; 321 if (effect.getFXLayer() == 0) 322 { 323 texture = "/particles.png"; 324 } 325 else if (effect.getFXLayer() == 2) 326 { 327 texture = "/gui/items.png"; 328 } 329 texture = ForgeHooks.getTexture(texture, obj); 330 effectList.put(texture, effect); 331 } 332 333 public void addBlockHitEffects(int x, int y, int z, MovingObjectPosition target) 334 { 335 Block block = Block.blocksList[worldObj.getBlockId(x, y, z)]; 336 if (block != null && !block.addBlockHitEffects(worldObj, target, this)) 337 { 338 addBlockHitEffects(x, y, z, target.sideHit); 339 } 340 } 341 }