001package net.minecraft.block; 002 003import java.util.Random; 004import net.minecraft.block.material.Material; 005import net.minecraft.creativetab.CreativeTabs; 006import net.minecraft.util.AxisAlignedBB; 007import net.minecraft.util.Direction; 008import net.minecraft.world.IBlockAccess; 009import net.minecraft.world.World; 010 011import net.minecraftforge.common.ForgeDirection; 012import static net.minecraftforge.common.ForgeDirection.*; 013 014public class BlockTripWireSource extends Block 015{ 016 public BlockTripWireSource(int par1) 017 { 018 super(par1, Material.circuits); 019 this.setCreativeTab(CreativeTabs.tabRedstone); 020 this.setTickRandomly(true); 021 } 022 023 /** 024 * Returns a bounding box from the pool of bounding boxes (this means this box can change after the pool has been 025 * cleared to be reused) 026 */ 027 public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4) 028 { 029 return null; 030 } 031 032 /** 033 * Is this block (a) opaque and (b) a full 1m cube? This determines whether or not to render the shared face of two 034 * adjacent blocks and also whether the player can attach torches, redstone wire, etc to this block. 035 */ 036 public boolean isOpaqueCube() 037 { 038 return false; 039 } 040 041 /** 042 * If this block doesn't render as an ordinary block it will return False (examples: signs, buttons, stairs, etc) 043 */ 044 public boolean renderAsNormalBlock() 045 { 046 return false; 047 } 048 049 /** 050 * The type of render function that is called for this block 051 */ 052 public int getRenderType() 053 { 054 return 29; 055 } 056 057 /** 058 * How many world ticks before ticking 059 */ 060 public int tickRate(World par1World) 061 { 062 return 10; 063 } 064 065 /** 066 * checks to see if you can place this block can be placed on that side of a block: BlockLever overrides 067 */ 068 public boolean canPlaceBlockOnSide(World par1World, int par2, int par3, int par4, int par5) 069 { 070 ForgeDirection dir = ForgeDirection.getOrientation(par5); 071 return (dir == NORTH && par1World.isBlockSolidOnSide(par2, par3, par4 + 1, NORTH)) || 072 (dir == SOUTH && par1World.isBlockSolidOnSide(par2, par3, par4 - 1, SOUTH)) || 073 (dir == WEST && par1World.isBlockSolidOnSide(par2 + 1, par3, par4, WEST )) || 074 (dir == EAST && par1World.isBlockSolidOnSide(par2 - 1, par3, par4, EAST )); 075 } 076 077 /** 078 * Checks to see if its valid to put this block at the specified coordinates. Args: world, x, y, z 079 */ 080 public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4) 081 { 082 return par1World.isBlockSolidOnSide(par2 - 1, par3, par4, SOUTH) || 083 par1World.isBlockSolidOnSide(par2 + 1, par3, par4, NORTH) || 084 par1World.isBlockSolidOnSide(par2, par3, par4 - 1, EAST ) || 085 par1World.isBlockSolidOnSide(par2, par3, par4 + 1, WEST ); 086 } 087 088 /** 089 * Called when a block is placed using its ItemBlock. Args: World, X, Y, Z, side, hitX, hitY, hitZ, block metadata 090 */ 091 public int onBlockPlaced(World par1World, int par2, int par3, int par4, int par5, float par6, float par7, float par8, int par9) 092 { 093 byte b0 = 0; 094 095 if (par5 == 2 && par1World.isBlockSolidOnSide(par2, par3, par4 + 1, WEST, true)) 096 { 097 b0 = 2; 098 } 099 100 if (par5 == 3 && par1World.isBlockSolidOnSide(par2, par3, par4 - 1, EAST, true)) 101 { 102 b0 = 0; 103 } 104 105 if (par5 == 4 && par1World.isBlockSolidOnSide(par2 + 1, par3, par4, NORTH, true)) 106 { 107 b0 = 1; 108 } 109 110 if (par5 == 5 && par1World.isBlockSolidOnSide(par2 - 1, par3, par4, SOUTH, true)) 111 { 112 b0 = 3; 113 } 114 115 return b0; 116 } 117 118 /** 119 * Called after a block is placed 120 */ 121 public void onPostBlockPlaced(World par1World, int par2, int par3, int par4, int par5) 122 { 123 this.func_72143_a(par1World, par2, par3, par4, this.blockID, par5, false, -1, 0); 124 } 125 126 /** 127 * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are 128 * their own) Args: x, y, z, neighbor blockID 129 */ 130 public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) 131 { 132 if (par5 != this.blockID) 133 { 134 if (this.func_72144_l(par1World, par2, par3, par4)) 135 { 136 int i1 = par1World.getBlockMetadata(par2, par3, par4); 137 int j1 = i1 & 3; 138 boolean flag = false; 139 140 if (!par1World.isBlockSolidOnSide(par2 - 1, par3, par4, SOUTH) && j1 == 3) 141 { 142 flag = true; 143 } 144 145 if (!par1World.isBlockSolidOnSide(par2 + 1, par3, par4, NORTH) && j1 == 1) 146 { 147 flag = true; 148 } 149 150 if (!par1World.isBlockSolidOnSide(par2, par3, par4 - 1, EAST) && j1 == 0) 151 { 152 flag = true; 153 } 154 155 if (!par1World.isBlockSolidOnSide(par2, par3, par4 + 1, WEST) && j1 == 2) 156 { 157 flag = true; 158 } 159 160 if (flag) 161 { 162 this.dropBlockAsItem(par1World, par2, par3, par4, i1, 0); 163 par1World.setBlockToAir(par2, par3, par4); 164 } 165 } 166 } 167 } 168 169 public void func_72143_a(World par1World, int par2, int par3, int par4, int par5, int par6, boolean par7, int par8, int par9) 170 { 171 int l1 = par6 & 3; 172 boolean flag1 = (par6 & 4) == 4; 173 boolean flag2 = (par6 & 8) == 8; 174 boolean flag3 = par5 == Block.tripWireSource.blockID; 175 boolean flag4 = false; 176 boolean flag5 = !par1World.isBlockSolidOnSide(par2, par3 - 1, par4, UP); 177 int i2 = Direction.offsetX[l1]; 178 int j2 = Direction.offsetZ[l1]; 179 int k2 = 0; 180 int[] aint = new int[42]; 181 int l2; 182 int i3; 183 int j3; 184 int k3; 185 int l3; 186 187 for (i3 = 1; i3 < 42; ++i3) 188 { 189 l2 = par2 + i2 * i3; 190 k3 = par4 + j2 * i3; 191 j3 = par1World.getBlockId(l2, par3, k3); 192 193 if (j3 == Block.tripWireSource.blockID) 194 { 195 l3 = par1World.getBlockMetadata(l2, par3, k3); 196 197 if ((l3 & 3) == Direction.rotateOpposite[l1]) 198 { 199 k2 = i3; 200 } 201 202 break; 203 } 204 205 if (j3 != Block.tripWire.blockID && i3 != par8) 206 { 207 aint[i3] = -1; 208 flag3 = false; 209 } 210 else 211 { 212 l3 = i3 == par8 ? par9 : par1World.getBlockMetadata(l2, par3, k3); 213 boolean flag6 = (l3 & 8) != 8; 214 boolean flag7 = (l3 & 1) == 1; 215 boolean flag8 = (l3 & 2) == 2; 216 flag3 &= flag8 == flag5; 217 flag4 |= flag6 && flag7; 218 aint[i3] = l3; 219 220 if (i3 == par8) 221 { 222 par1World.scheduleBlockUpdate(par2, par3, par4, par5, this.tickRate(par1World)); 223 flag3 &= flag6; 224 } 225 } 226 } 227 228 flag3 &= k2 > 1; 229 flag4 &= flag3; 230 i3 = (flag3 ? 4 : 0) | (flag4 ? 8 : 0); 231 par6 = l1 | i3; 232 233 if (k2 > 0) 234 { 235 l2 = par2 + i2 * k2; 236 k3 = par4 + j2 * k2; 237 j3 = Direction.rotateOpposite[l1]; 238 par1World.setBlockMetadataWithNotify(l2, par3, k3, j3 | i3, 3); 239 this.notifyNeighborOfChange(par1World, l2, par3, k3, j3); 240 this.playSoundEffect(par1World, l2, par3, k3, flag3, flag4, flag1, flag2); 241 } 242 243 this.playSoundEffect(par1World, par2, par3, par4, flag3, flag4, flag1, flag2); 244 245 if (par5 > 0) 246 { 247 par1World.setBlockMetadataWithNotify(par2, par3, par4, par6, 3); 248 249 if (par7) 250 { 251 this.notifyNeighborOfChange(par1World, par2, par3, par4, l1); 252 } 253 } 254 255 if (flag1 != flag3) 256 { 257 for (l2 = 1; l2 < k2; ++l2) 258 { 259 k3 = par2 + i2 * l2; 260 j3 = par4 + j2 * l2; 261 l3 = aint[l2]; 262 263 if (l3 >= 0) 264 { 265 if (flag3) 266 { 267 l3 |= 4; 268 } 269 else 270 { 271 l3 &= -5; 272 } 273 274 par1World.setBlockMetadataWithNotify(k3, par3, j3, l3, 3); 275 } 276 } 277 } 278 } 279 280 /** 281 * Ticks the block if it's been scheduled 282 */ 283 public void updateTick(World par1World, int par2, int par3, int par4, Random par5Random) 284 { 285 this.func_72143_a(par1World, par2, par3, par4, this.blockID, par1World.getBlockMetadata(par2, par3, par4), true, -1, 0); 286 } 287 288 /** 289 * only of the conditions are right 290 */ 291 private void playSoundEffect(World par1World, int par2, int par3, int par4, boolean par5, boolean par6, boolean par7, boolean par8) 292 { 293 if (par6 && !par8) 294 { 295 par1World.playSoundEffect((double)par2 + 0.5D, (double)par3 + 0.1D, (double)par4 + 0.5D, "random.click", 0.4F, 0.6F); 296 } 297 else if (!par6 && par8) 298 { 299 par1World.playSoundEffect((double)par2 + 0.5D, (double)par3 + 0.1D, (double)par4 + 0.5D, "random.click", 0.4F, 0.5F); 300 } 301 else if (par5 && !par7) 302 { 303 par1World.playSoundEffect((double)par2 + 0.5D, (double)par3 + 0.1D, (double)par4 + 0.5D, "random.click", 0.4F, 0.7F); 304 } 305 else if (!par5 && par7) 306 { 307 par1World.playSoundEffect((double)par2 + 0.5D, (double)par3 + 0.1D, (double)par4 + 0.5D, "random.bowhit", 0.4F, 1.2F / (par1World.rand.nextFloat() * 0.2F + 0.9F)); 308 } 309 } 310 311 private void notifyNeighborOfChange(World par1World, int par2, int par3, int par4, int par5) 312 { 313 par1World.notifyBlocksOfNeighborChange(par2, par3, par4, this.blockID); 314 315 if (par5 == 3) 316 { 317 par1World.notifyBlocksOfNeighborChange(par2 - 1, par3, par4, this.blockID); 318 } 319 else if (par5 == 1) 320 { 321 par1World.notifyBlocksOfNeighborChange(par2 + 1, par3, par4, this.blockID); 322 } 323 else if (par5 == 0) 324 { 325 par1World.notifyBlocksOfNeighborChange(par2, par3, par4 - 1, this.blockID); 326 } 327 else if (par5 == 2) 328 { 329 par1World.notifyBlocksOfNeighborChange(par2, par3, par4 + 1, this.blockID); 330 } 331 } 332 333 private boolean func_72144_l(World par1World, int par2, int par3, int par4) 334 { 335 if (!this.canPlaceBlockAt(par1World, par2, par3, par4)) 336 { 337 this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0); 338 par1World.setBlockToAir(par2, par3, par4); 339 return false; 340 } 341 else 342 { 343 return true; 344 } 345 } 346 347 /** 348 * Updates the blocks bounds based on its current state. Args: world, x, y, z 349 */ 350 public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) 351 { 352 int l = par1IBlockAccess.getBlockMetadata(par2, par3, par4) & 3; 353 float f = 0.1875F; 354 355 if (l == 3) 356 { 357 this.setBlockBounds(0.0F, 0.2F, 0.5F - f, f * 2.0F, 0.8F, 0.5F + f); 358 } 359 else if (l == 1) 360 { 361 this.setBlockBounds(1.0F - f * 2.0F, 0.2F, 0.5F - f, 1.0F, 0.8F, 0.5F + f); 362 } 363 else if (l == 0) 364 { 365 this.setBlockBounds(0.5F - f, 0.2F, 0.0F, 0.5F + f, 0.8F, f * 2.0F); 366 } 367 else if (l == 2) 368 { 369 this.setBlockBounds(0.5F - f, 0.2F, 1.0F - f * 2.0F, 0.5F + f, 0.8F, 1.0F); 370 } 371 } 372 373 /** 374 * ejects contained items into the world, and notifies neighbours of an update, as appropriate 375 */ 376 public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6) 377 { 378 boolean flag = (par6 & 4) == 4; 379 boolean flag1 = (par6 & 8) == 8; 380 381 if (flag || flag1) 382 { 383 this.func_72143_a(par1World, par2, par3, par4, 0, par6, false, -1, 0); 384 } 385 386 if (flag1) 387 { 388 par1World.notifyBlocksOfNeighborChange(par2, par3, par4, this.blockID); 389 int j1 = par6 & 3; 390 391 if (j1 == 3) 392 { 393 par1World.notifyBlocksOfNeighborChange(par2 - 1, par3, par4, this.blockID); 394 } 395 else if (j1 == 1) 396 { 397 par1World.notifyBlocksOfNeighborChange(par2 + 1, par3, par4, this.blockID); 398 } 399 else if (j1 == 0) 400 { 401 par1World.notifyBlocksOfNeighborChange(par2, par3, par4 - 1, this.blockID); 402 } 403 else if (j1 == 2) 404 { 405 par1World.notifyBlocksOfNeighborChange(par2, par3, par4 + 1, this.blockID); 406 } 407 } 408 409 super.breakBlock(par1World, par2, par3, par4, par5, par6); 410 } 411 412 /** 413 * Returns true if the block is emitting indirect/weak redstone power on the specified side. If isBlockNormalCube 414 * returns true, standard redstone propagation rules will apply instead and this will not be called. Args: World, X, 415 * Y, Z, side. Note that the side is reversed - eg it is 1 (up) when checking the bottom of the block. 416 */ 417 public int isProvidingWeakPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) 418 { 419 return (par1IBlockAccess.getBlockMetadata(par2, par3, par4) & 8) == 8 ? 15 : 0; 420 } 421 422 /** 423 * Returns true if the block is emitting direct/strong redstone power on the specified side. Args: World, X, Y, Z, 424 * side. Note that the side is reversed - eg it is 1 (up) when checking the bottom of the block. 425 */ 426 public int isProvidingStrongPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) 427 { 428 int i1 = par1IBlockAccess.getBlockMetadata(par2, par3, par4); 429 430 if ((i1 & 8) != 8) 431 { 432 return 0; 433 } 434 else 435 { 436 int j1 = i1 & 3; 437 return j1 == 2 && par5 == 2 ? 15 : (j1 == 0 && par5 == 3 ? 15 : (j1 == 1 && par5 == 4 ? 15 : (j1 == 3 && par5 == 5 ? 15 : 0))); 438 } 439 } 440 441 /** 442 * Can this block provide power. Only wire currently seems to have this change based on its state. 443 */ 444 public boolean canProvidePower() 445 { 446 return true; 447 } 448}