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.HashMap; 007 import java.util.Iterator; 008 import java.util.List; 009 import java.util.Map; 010 import java.util.Random; 011 012 public class BlockRedstoneTorch extends BlockTorch 013 { 014 /** Whether the redstone torch is currently active or not. */ 015 private boolean torchActive = false; 016 017 /** Map of ArrayLists of RedstoneUpdateInfo. Key of map is World. */ 018 private static Map redstoneUpdateInfoCache = new HashMap(); 019 020 /** 021 * From the specified side and block metadata retrieves the blocks texture. Args: side, metadata 022 */ 023 public int getBlockTextureFromSideAndMetadata(int par1, int par2) 024 { 025 return par1 == 1 ? Block.redstoneWire.getBlockTextureFromSideAndMetadata(par1, par2) : super.getBlockTextureFromSideAndMetadata(par1, par2); 026 } 027 028 private boolean checkForBurnout(World par1World, int par2, int par3, int par4, boolean par5) 029 { 030 if (!redstoneUpdateInfoCache.containsKey(par1World)) 031 { 032 redstoneUpdateInfoCache.put(par1World, new ArrayList()); 033 } 034 035 if (par5) 036 { 037 ((List)redstoneUpdateInfoCache.get(par1World)).add(new RedstoneUpdateInfo(par2, par3, par4, par1World.func_82737_E())); 038 } 039 040 int var6 = 0; 041 Iterator var7 = ((List)redstoneUpdateInfoCache.get(par1World)).iterator(); 042 043 while (var7.hasNext()) 044 { 045 RedstoneUpdateInfo var8 = (RedstoneUpdateInfo)var7.next(); 046 047 if (var8.x == par2 && var8.y == par3 && var8.z == par4) 048 { 049 ++var6; 050 051 if (var6 >= 8) 052 { 053 return true; 054 } 055 } 056 } 057 058 return false; 059 } 060 061 protected BlockRedstoneTorch(int par1, int par2, boolean par3) 062 { 063 super(par1, par2); 064 this.torchActive = par3; 065 this.setTickRandomly(true); 066 this.setCreativeTab((CreativeTabs)null); 067 } 068 069 /** 070 * How many world ticks before ticking 071 */ 072 public int tickRate() 073 { 074 return 2; 075 } 076 077 /** 078 * Called whenever the block is added into the world. Args: world, x, y, z 079 */ 080 public void onBlockAdded(World par1World, int par2, int par3, int par4) 081 { 082 if (par1World.getBlockMetadata(par2, par3, par4) == 0) 083 { 084 super.onBlockAdded(par1World, par2, par3, par4); 085 } 086 087 if (this.torchActive) 088 { 089 par1World.notifyBlocksOfNeighborChange(par2, par3 - 1, par4, this.blockID); 090 par1World.notifyBlocksOfNeighborChange(par2, par3 + 1, par4, this.blockID); 091 par1World.notifyBlocksOfNeighborChange(par2 - 1, par3, par4, this.blockID); 092 par1World.notifyBlocksOfNeighborChange(par2 + 1, par3, par4, this.blockID); 093 par1World.notifyBlocksOfNeighborChange(par2, par3, par4 - 1, this.blockID); 094 par1World.notifyBlocksOfNeighborChange(par2, par3, par4 + 1, this.blockID); 095 } 096 } 097 098 /** 099 * ejects contained items into the world, and notifies neighbours of an update, as appropriate 100 */ 101 public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6) 102 { 103 if (this.torchActive) 104 { 105 par1World.notifyBlocksOfNeighborChange(par2, par3 - 1, par4, this.blockID); 106 par1World.notifyBlocksOfNeighborChange(par2, par3 + 1, par4, this.blockID); 107 par1World.notifyBlocksOfNeighborChange(par2 - 1, par3, par4, this.blockID); 108 par1World.notifyBlocksOfNeighborChange(par2 + 1, par3, par4, this.blockID); 109 par1World.notifyBlocksOfNeighborChange(par2, par3, par4 - 1, this.blockID); 110 par1World.notifyBlocksOfNeighborChange(par2, par3, par4 + 1, this.blockID); 111 } 112 } 113 114 /** 115 * Is this block powering the block on the specified side 116 */ 117 public boolean isPoweringTo(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) 118 { 119 if (!this.torchActive) 120 { 121 return false; 122 } 123 else 124 { 125 int var6 = par1IBlockAccess.getBlockMetadata(par2, par3, par4); 126 return var6 == 5 && par5 == 1 ? false : (var6 == 3 && par5 == 3 ? false : (var6 == 4 && par5 == 2 ? false : (var6 == 1 && par5 == 5 ? false : var6 != 2 || par5 != 4))); 127 } 128 } 129 130 /** 131 * Returns true or false based on whether the block the torch is attached to is providing indirect power. 132 */ 133 private boolean isIndirectlyPowered(World par1World, int par2, int par3, int par4) 134 { 135 int var5 = par1World.getBlockMetadata(par2, par3, par4); 136 return var5 == 5 && par1World.isBlockIndirectlyProvidingPowerTo(par2, par3 - 1, par4, 0) ? true : (var5 == 3 && par1World.isBlockIndirectlyProvidingPowerTo(par2, par3, par4 - 1, 2) ? true : (var5 == 4 && par1World.isBlockIndirectlyProvidingPowerTo(par2, par3, par4 + 1, 3) ? true : (var5 == 1 && par1World.isBlockIndirectlyProvidingPowerTo(par2 - 1, par3, par4, 4) ? true : var5 == 2 && par1World.isBlockIndirectlyProvidingPowerTo(par2 + 1, par3, par4, 5)))); 137 } 138 139 /** 140 * Ticks the block if it's been scheduled 141 */ 142 public void updateTick(World par1World, int par2, int par3, int par4, Random par5Random) 143 { 144 boolean var6 = this.isIndirectlyPowered(par1World, par2, par3, par4); 145 List var7 = (List)redstoneUpdateInfoCache.get(par1World); 146 147 while (var7 != null && !var7.isEmpty() && par1World.func_82737_E() - ((RedstoneUpdateInfo)var7.get(0)).updateTime > 60L) 148 { 149 var7.remove(0); 150 } 151 152 if (this.torchActive) 153 { 154 if (var6) 155 { 156 par1World.setBlockAndMetadataWithNotify(par2, par3, par4, Block.torchRedstoneIdle.blockID, par1World.getBlockMetadata(par2, par3, par4)); 157 158 if (this.checkForBurnout(par1World, par2, par3, par4, true)) 159 { 160 par1World.playSoundEffect((double)((float)par2 + 0.5F), (double)((float)par3 + 0.5F), (double)((float)par4 + 0.5F), "random.fizz", 0.5F, 2.6F + (par1World.rand.nextFloat() - par1World.rand.nextFloat()) * 0.8F); 161 162 for (int var8 = 0; var8 < 5; ++var8) 163 { 164 double var9 = (double)par2 + par5Random.nextDouble() * 0.6D + 0.2D; 165 double var11 = (double)par3 + par5Random.nextDouble() * 0.6D + 0.2D; 166 double var13 = (double)par4 + par5Random.nextDouble() * 0.6D + 0.2D; 167 par1World.spawnParticle("smoke", var9, var11, var13, 0.0D, 0.0D, 0.0D); 168 } 169 } 170 } 171 } 172 else if (!var6 && !this.checkForBurnout(par1World, par2, par3, par4, false)) 173 { 174 par1World.setBlockAndMetadataWithNotify(par2, par3, par4, Block.torchRedstoneActive.blockID, par1World.getBlockMetadata(par2, par3, par4)); 175 } 176 } 177 178 /** 179 * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are 180 * their own) Args: x, y, z, neighbor blockID 181 */ 182 public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) 183 { 184 super.onNeighborBlockChange(par1World, par2, par3, par4, par5); 185 par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, this.tickRate()); 186 } 187 188 /** 189 * Is this block indirectly powering the block on the specified side 190 */ 191 public boolean isIndirectlyPoweringTo(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) 192 { 193 return par5 == 0 ? this.isPoweringTo(par1IBlockAccess, par2, par3, par4, par5) : false; 194 } 195 196 /** 197 * Returns the ID of the items to drop on destruction. 198 */ 199 public int idDropped(int par1, Random par2Random, int par3) 200 { 201 return Block.torchRedstoneActive.blockID; 202 } 203 204 /** 205 * Can this block provide power. Only wire currently seems to have this change based on its state. 206 */ 207 public boolean canProvidePower() 208 { 209 return true; 210 } 211 212 @SideOnly(Side.CLIENT) 213 214 /** 215 * A randomly called display update to be able to add particles or other items for display 216 */ 217 public void randomDisplayTick(World par1World, int par2, int par3, int par4, Random par5Random) 218 { 219 if (this.torchActive) 220 { 221 int var6 = par1World.getBlockMetadata(par2, par3, par4); 222 double var7 = (double)((float)par2 + 0.5F) + (double)(par5Random.nextFloat() - 0.5F) * 0.2D; 223 double var9 = (double)((float)par3 + 0.7F) + (double)(par5Random.nextFloat() - 0.5F) * 0.2D; 224 double var11 = (double)((float)par4 + 0.5F) + (double)(par5Random.nextFloat() - 0.5F) * 0.2D; 225 double var13 = 0.2199999988079071D; 226 double var15 = 0.27000001072883606D; 227 228 if (var6 == 1) 229 { 230 par1World.spawnParticle("reddust", var7 - var15, var9 + var13, var11, 0.0D, 0.0D, 0.0D); 231 } 232 else if (var6 == 2) 233 { 234 par1World.spawnParticle("reddust", var7 + var15, var9 + var13, var11, 0.0D, 0.0D, 0.0D); 235 } 236 else if (var6 == 3) 237 { 238 par1World.spawnParticle("reddust", var7, var9 + var13, var11 - var15, 0.0D, 0.0D, 0.0D); 239 } 240 else if (var6 == 4) 241 { 242 par1World.spawnParticle("reddust", var7, var9 + var13, var11 + var15, 0.0D, 0.0D, 0.0D); 243 } 244 else 245 { 246 par1World.spawnParticle("reddust", var7, var9, var11, 0.0D, 0.0D, 0.0D); 247 } 248 } 249 } 250 251 @SideOnly(Side.CLIENT) 252 253 /** 254 * only called by clickMiddleMouseButton , and passed to inventory.setCurrentItem (along with isCreative) 255 */ 256 public int idPicked(World par1World, int par2, int par3, int par4) 257 { 258 return Block.torchRedstoneActive.blockID; 259 } 260 }