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