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 }