001package net.minecraft.block; 002 003import cpw.mods.fml.relauncher.Side; 004import cpw.mods.fml.relauncher.SideOnly; 005import java.util.ArrayList; 006import java.util.HashMap; 007import java.util.List; 008import java.util.Map; 009import java.util.Random; 010import net.minecraft.client.renderer.texture.IconRegister; 011import net.minecraft.creativetab.CreativeTabs; 012import net.minecraft.world.IBlockAccess; 013import net.minecraft.world.World; 014 015public class BlockRedstoneTorch extends BlockTorch 016{ 017 /** Whether the redstone torch is currently active or not. */ 018 private boolean torchActive = false; 019 020 /** Map of ArrayLists of RedstoneUpdateInfo. Key of map is World. */ 021 private static Map redstoneUpdateInfoCache = new HashMap(); 022 023 private boolean checkForBurnout(World par1World, int par2, int par3, int par4, boolean par5) 024 { 025 if (!redstoneUpdateInfoCache.containsKey(par1World)) 026 { 027 redstoneUpdateInfoCache.put(par1World, new ArrayList()); 028 } 029 030 List list = (List)redstoneUpdateInfoCache.get(par1World); 031 032 if (par5) 033 { 034 list.add(new RedstoneUpdateInfo(par2, par3, par4, par1World.getTotalWorldTime())); 035 } 036 037 int l = 0; 038 039 for (int i1 = 0; i1 < list.size(); ++i1) 040 { 041 RedstoneUpdateInfo redstoneupdateinfo = (RedstoneUpdateInfo)list.get(i1); 042 043 if (redstoneupdateinfo.x == par2 && redstoneupdateinfo.y == par3 && redstoneupdateinfo.z == par4) 044 { 045 ++l; 046 047 if (l >= 8) 048 { 049 return true; 050 } 051 } 052 } 053 054 return false; 055 } 056 057 protected BlockRedstoneTorch(int par1, boolean par2) 058 { 059 super(par1); 060 this.torchActive = par2; 061 this.setTickRandomly(true); 062 this.setCreativeTab((CreativeTabs)null); 063 } 064 065 /** 066 * How many world ticks before ticking 067 */ 068 public int tickRate(World par1World) 069 { 070 return 2; 071 } 072 073 /** 074 * Called whenever the block is added into the world. Args: world, x, y, z 075 */ 076 public void onBlockAdded(World par1World, int par2, int par3, int par4) 077 { 078 if (par1World.getBlockMetadata(par2, par3, par4) == 0) 079 { 080 super.onBlockAdded(par1World, par2, par3, par4); 081 } 082 083 if (this.torchActive) 084 { 085 par1World.notifyBlocksOfNeighborChange(par2, par3 - 1, par4, this.blockID); 086 par1World.notifyBlocksOfNeighborChange(par2, par3 + 1, par4, this.blockID); 087 par1World.notifyBlocksOfNeighborChange(par2 - 1, par3, par4, this.blockID); 088 par1World.notifyBlocksOfNeighborChange(par2 + 1, par3, par4, this.blockID); 089 par1World.notifyBlocksOfNeighborChange(par2, par3, par4 - 1, this.blockID); 090 par1World.notifyBlocksOfNeighborChange(par2, par3, par4 + 1, this.blockID); 091 } 092 } 093 094 /** 095 * ejects contained items into the world, and notifies neighbours of an update, as appropriate 096 */ 097 public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6) 098 { 099 if (this.torchActive) 100 { 101 par1World.notifyBlocksOfNeighborChange(par2, par3 - 1, par4, this.blockID); 102 par1World.notifyBlocksOfNeighborChange(par2, par3 + 1, par4, this.blockID); 103 par1World.notifyBlocksOfNeighborChange(par2 - 1, par3, par4, this.blockID); 104 par1World.notifyBlocksOfNeighborChange(par2 + 1, par3, par4, this.blockID); 105 par1World.notifyBlocksOfNeighborChange(par2, par3, par4 - 1, this.blockID); 106 par1World.notifyBlocksOfNeighborChange(par2, par3, par4 + 1, this.blockID); 107 } 108 } 109 110 /** 111 * Returns true if the block is emitting indirect/weak redstone power on the specified side. If isBlockNormalCube 112 * returns true, standard redstone propagation rules will apply instead and this will not be called. Args: World, X, 113 * Y, Z, side. Note that the side is reversed - eg it is 1 (up) when checking the bottom of the block. 114 */ 115 public int isProvidingWeakPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) 116 { 117 if (!this.torchActive) 118 { 119 return 0; 120 } 121 else 122 { 123 int i1 = par1IBlockAccess.getBlockMetadata(par2, par3, par4); 124 return i1 == 5 && par5 == 1 ? 0 : (i1 == 3 && par5 == 3 ? 0 : (i1 == 4 && par5 == 2 ? 0 : (i1 == 1 && par5 == 5 ? 0 : (i1 == 2 && par5 == 4 ? 0 : 15)))); 125 } 126 } 127 128 /** 129 * Returns true or false based on whether the block the torch is attached to is providing indirect power. 130 */ 131 private boolean isIndirectlyPowered(World par1World, int par2, int par3, int par4) 132 { 133 int l = par1World.getBlockMetadata(par2, par3, par4); 134 return l == 5 && par1World.getIndirectPowerOutput(par2, par3 - 1, par4, 0) ? true : (l == 3 && par1World.getIndirectPowerOutput(par2, par3, par4 - 1, 2) ? true : (l == 4 && par1World.getIndirectPowerOutput(par2, par3, par4 + 1, 3) ? true : (l == 1 && par1World.getIndirectPowerOutput(par2 - 1, par3, par4, 4) ? true : l == 2 && par1World.getIndirectPowerOutput(par2 + 1, par3, par4, 5)))); 135 } 136 137 /** 138 * Ticks the block if it's been scheduled 139 */ 140 public void updateTick(World par1World, int par2, int par3, int par4, Random par5Random) 141 { 142 boolean flag = this.isIndirectlyPowered(par1World, par2, par3, par4); 143 List list = (List)redstoneUpdateInfoCache.get(par1World); 144 145 while (list != null && !list.isEmpty() && par1World.getTotalWorldTime() - ((RedstoneUpdateInfo)list.get(0)).updateTime > 60L) 146 { 147 list.remove(0); 148 } 149 150 if (this.torchActive) 151 { 152 if (flag) 153 { 154 par1World.setBlock(par2, par3, par4, Block.torchRedstoneIdle.blockID, par1World.getBlockMetadata(par2, par3, par4), 3); 155 156 if (this.checkForBurnout(par1World, par2, par3, par4, true)) 157 { 158 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); 159 160 for (int l = 0; l < 5; ++l) 161 { 162 double d0 = (double)par2 + par5Random.nextDouble() * 0.6D + 0.2D; 163 double d1 = (double)par3 + par5Random.nextDouble() * 0.6D + 0.2D; 164 double d2 = (double)par4 + par5Random.nextDouble() * 0.6D + 0.2D; 165 par1World.spawnParticle("smoke", d0, d1, d2, 0.0D, 0.0D, 0.0D); 166 } 167 } 168 } 169 } 170 else if (!flag && !this.checkForBurnout(par1World, par2, par3, par4, false)) 171 { 172 par1World.setBlock(par2, par3, par4, Block.torchRedstoneActive.blockID, par1World.getBlockMetadata(par2, par3, par4), 3); 173 } 174 } 175 176 /** 177 * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are 178 * their own) Args: x, y, z, neighbor blockID 179 */ 180 public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) 181 { 182 if (!this.func_94397_d(par1World, par2, par3, par4, par5)) 183 { 184 boolean flag = this.isIndirectlyPowered(par1World, par2, par3, par4); 185 186 if (this.torchActive && flag || !this.torchActive && !flag) 187 { 188 par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, this.tickRate(par1World)); 189 } 190 } 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 int isProvidingStrongPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) 198 { 199 return par5 == 0 ? this.isProvidingWeakPower(par1IBlockAccess, par2, par3, par4, par5) : 0; 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 l = par1World.getBlockMetadata(par2, par3, par4); 228 double d0 = (double)((float)par2 + 0.5F) + (double)(par5Random.nextFloat() - 0.5F) * 0.2D; 229 double d1 = (double)((float)par3 + 0.7F) + (double)(par5Random.nextFloat() - 0.5F) * 0.2D; 230 double d2 = (double)((float)par4 + 0.5F) + (double)(par5Random.nextFloat() - 0.5F) * 0.2D; 231 double d3 = 0.2199999988079071D; 232 double d4 = 0.27000001072883606D; 233 234 if (l == 1) 235 { 236 par1World.spawnParticle("reddust", d0 - d4, d1 + d3, d2, 0.0D, 0.0D, 0.0D); 237 } 238 else if (l == 2) 239 { 240 par1World.spawnParticle("reddust", d0 + d4, d1 + d3, d2, 0.0D, 0.0D, 0.0D); 241 } 242 else if (l == 3) 243 { 244 par1World.spawnParticle("reddust", d0, d1 + d3, d2 - d4, 0.0D, 0.0D, 0.0D); 245 } 246 else if (l == 4) 247 { 248 par1World.spawnParticle("reddust", d0, d1 + d3, d2 + d4, 0.0D, 0.0D, 0.0D); 249 } 250 else 251 { 252 par1World.spawnParticle("reddust", d0, d1, d2, 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 267 /** 268 * Returns true if the given block ID is equivalent to this one. Example: redstoneTorchOn matches itself and 269 * redstoneTorchOff, and vice versa. Most blocks only match themselves. 270 */ 271 public boolean isAssociatedBlockID(int par1) 272 { 273 return par1 == Block.torchRedstoneIdle.blockID || par1 == Block.torchRedstoneActive.blockID; 274 } 275 276 @SideOnly(Side.CLIENT) 277 278 /** 279 * When this method is called, your block should register all the icons it needs with the given IconRegister. This 280 * is the only chance you get to register icons. 281 */ 282 public void registerIcons(IconRegister par1IconRegister) 283 { 284 if (this.torchActive) 285 { 286 this.blockIcon = par1IconRegister.registerIcon("redtorch_lit"); 287 } 288 else 289 { 290 this.blockIcon = par1IconRegister.registerIcon("redtorch"); 291 } 292 } 293}