001 package net.minecraft.block; 002 003 import java.util.Random; 004 import net.minecraft.block.material.Material; 005 import net.minecraft.creativetab.CreativeTabs; 006 import net.minecraft.util.AxisAlignedBB; 007 import net.minecraft.util.Direction; 008 import net.minecraft.world.IBlockAccess; 009 import net.minecraft.world.World; 010 011 import net.minecraftforge.common.ForgeDirection; 012 import static net.minecraftforge.common.ForgeDirection.*; 013 014 public class BlockTripWireSource extends Block 015 { 016 public BlockTripWireSource(int par1) 017 { 018 super(par1, 172, 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() 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 var10 = 0; 094 095 if (par5 == 2 && par1World.isBlockSolidOnSide(par2, par3, par4 + 1, WEST, true)) 096 { 097 var10 = 2; 098 } 099 100 if (par5 == 3 && par1World.isBlockSolidOnSide(par2, par3, par4 - 1, EAST, true)) 101 { 102 var10 = 0; 103 } 104 105 if (par5 == 4 && par1World.isBlockSolidOnSide(par2 + 1, par3, par4, NORTH, true)) 106 { 107 var10 = 1; 108 } 109 110 if (par5 == 5 && par1World.isBlockSolidOnSide(par2 - 1, par3, par4, SOUTH, true)) 111 { 112 var10 = 3; 113 } 114 115 return var10; 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 var6 = par1World.getBlockMetadata(par2, par3, par4); 137 int var7 = var6 & 3; 138 boolean var8 = false; 139 140 if (!par1World.isBlockSolidOnSide(par2 - 1, par3, par4, SOUTH) && var7 == 3) 141 { 142 var8 = true; 143 } 144 145 if (!par1World.isBlockSolidOnSide(par2 + 1, par3, par4, NORTH) && var7 == 1) 146 { 147 var8 = true; 148 } 149 150 if (!par1World.isBlockSolidOnSide(par2, par3, par4 - 1, EAST) && var7 == 0) 151 { 152 var8 = true; 153 } 154 155 if (!par1World.isBlockSolidOnSide(par2, par3, par4 + 1, WEST) && var7 == 2) 156 { 157 var8 = true; 158 } 159 160 if (var8) 161 { 162 this.dropBlockAsItem(par1World, par2, par3, par4, var6, 0); 163 par1World.setBlockWithNotify(par2, par3, par4, 0); 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 var10 = par6 & 3; 172 boolean var11 = (par6 & 4) == 4; 173 boolean var12 = (par6 & 8) == 8; 174 boolean var13 = par5 == Block.tripWireSource.blockID; 175 boolean var14 = false; 176 boolean var15 = !par1World.isBlockSolidOnSide(par2, par3 - 1, par4, UP); 177 int var16 = Direction.offsetX[var10]; 178 int var17 = Direction.offsetZ[var10]; 179 int var18 = 0; 180 int[] var19 = new int[42]; 181 int var21; 182 int var20; 183 int var23; 184 int var22; 185 int var24; 186 187 for (var20 = 1; var20 < 42; ++var20) 188 { 189 var21 = par2 + var16 * var20; 190 var22 = par4 + var17 * var20; 191 var23 = par1World.getBlockId(var21, par3, var22); 192 193 if (var23 == Block.tripWireSource.blockID) 194 { 195 var24 = par1World.getBlockMetadata(var21, par3, var22); 196 197 if ((var24 & 3) == Direction.footInvisibleFaceRemap[var10]) 198 { 199 var18 = var20; 200 } 201 202 break; 203 } 204 205 if (var23 != Block.tripWire.blockID && var20 != par8) 206 { 207 var19[var20] = -1; 208 var13 = false; 209 } 210 else 211 { 212 var24 = var20 == par8 ? par9 : par1World.getBlockMetadata(var21, par3, var22); 213 boolean var25 = (var24 & 8) != 8; 214 boolean var26 = (var24 & 1) == 1; 215 boolean var27 = (var24 & 2) == 2; 216 var13 &= var27 == var15; 217 var14 |= var25 && var26; 218 var19[var20] = var24; 219 220 if (var20 == par8) 221 { 222 par1World.scheduleBlockUpdate(par2, par3, par4, par5, this.tickRate()); 223 var13 &= var25; 224 } 225 } 226 } 227 228 var13 &= var18 > 1; 229 var14 &= var13; 230 var20 = (var13 ? 4 : 0) | (var14 ? 8 : 0); 231 par6 = var10 | var20; 232 233 if (var18 > 0) 234 { 235 var21 = par2 + var16 * var18; 236 var22 = par4 + var17 * var18; 237 var23 = Direction.footInvisibleFaceRemap[var10]; 238 par1World.setBlockMetadataWithNotify(var21, par3, var22, var23 | var20); 239 this.notifyNeighborOfChange(par1World, var21, par3, var22, var23); 240 this.playSoundEffect(par1World, var21, par3, var22, var13, var14, var11, var12); 241 } 242 243 this.playSoundEffect(par1World, par2, par3, par4, var13, var14, var11, var12); 244 245 if (par5 > 0) 246 { 247 par1World.setBlockMetadataWithNotify(par2, par3, par4, par6); 248 249 if (par7) 250 { 251 this.notifyNeighborOfChange(par1World, par2, par3, par4, var10); 252 } 253 } 254 255 if (var11 != var13) 256 { 257 for (var21 = 1; var21 < var18; ++var21) 258 { 259 var22 = par2 + var16 * var21; 260 var23 = par4 + var17 * var21; 261 var24 = var19[var21]; 262 263 if (var24 >= 0) 264 { 265 if (var13) 266 { 267 var24 |= 4; 268 } 269 else 270 { 271 var24 &= -5; 272 } 273 274 par1World.setBlockMetadataWithNotify(var22, par3, var23, var24); 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.setBlockWithNotify(par2, par3, par4, 0); 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 var5 = par1IBlockAccess.getBlockMetadata(par2, par3, par4) & 3; 353 float var6 = 0.1875F; 354 355 if (var5 == 3) 356 { 357 this.setBlockBounds(0.0F, 0.2F, 0.5F - var6, var6 * 2.0F, 0.8F, 0.5F + var6); 358 } 359 else if (var5 == 1) 360 { 361 this.setBlockBounds(1.0F - var6 * 2.0F, 0.2F, 0.5F - var6, 1.0F, 0.8F, 0.5F + var6); 362 } 363 else if (var5 == 0) 364 { 365 this.setBlockBounds(0.5F - var6, 0.2F, 0.0F, 0.5F + var6, 0.8F, var6 * 2.0F); 366 } 367 else if (var5 == 2) 368 { 369 this.setBlockBounds(0.5F - var6, 0.2F, 1.0F - var6 * 2.0F, 0.5F + var6, 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 var7 = (par6 & 4) == 4; 379 boolean var8 = (par6 & 8) == 8; 380 381 if (var7 || var8) 382 { 383 this.func_72143_a(par1World, par2, par3, par4, 0, par6, false, -1, 0); 384 } 385 386 if (var8) 387 { 388 par1World.notifyBlocksOfNeighborChange(par2, par3, par4, this.blockID); 389 int var9 = par6 & 3; 390 391 if (var9 == 3) 392 { 393 par1World.notifyBlocksOfNeighborChange(par2 - 1, par3, par4, this.blockID); 394 } 395 else if (var9 == 1) 396 { 397 par1World.notifyBlocksOfNeighborChange(par2 + 1, par3, par4, this.blockID); 398 } 399 else if (var9 == 0) 400 { 401 par1World.notifyBlocksOfNeighborChange(par2, par3, par4 - 1, this.blockID); 402 } 403 else if (var9 == 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 boolean isProvidingWeakPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) 418 { 419 return (par1IBlockAccess.getBlockMetadata(par2, par3, par4) & 8) == 8; 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 boolean isProvidingStrongPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) 427 { 428 int var6 = par1IBlockAccess.getBlockMetadata(par2, par3, par4); 429 430 if ((var6 & 8) != 8) 431 { 432 return false; 433 } 434 else 435 { 436 int var7 = var6 & 3; 437 return var7 == 2 && par5 == 2 ? true : (var7 == 0 && par5 == 3 ? true : (var7 == 1 && par5 == 4 ? true : var7 == 3 && par5 == 5)); 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 }