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.HashSet; 007 import java.util.Iterator; 008 import java.util.Random; 009 import java.util.Set; 010 011 public class BlockRedstoneWire extends Block 012 { 013 /** 014 * When false, power transmission methods do not look at other redstone wires. Used internally during 015 * updateCurrentStrength. 016 */ 017 private boolean wiresProvidePower = true; 018 private Set blocksNeedingUpdate = new HashSet(); 019 020 public BlockRedstoneWire(int par1, int par2) 021 { 022 super(par1, par2, Material.circuits); 023 this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.0625F, 1.0F); 024 } 025 026 /** 027 * From the specified side and block metadata retrieves the blocks texture. Args: side, metadata 028 */ 029 public int getBlockTextureFromSideAndMetadata(int par1, int par2) 030 { 031 return this.blockIndexInTexture; 032 } 033 034 /** 035 * Returns a bounding box from the pool of bounding boxes (this means this box can change after the pool has been 036 * cleared to be reused) 037 */ 038 public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4) 039 { 040 return null; 041 } 042 043 /** 044 * Is this block (a) opaque and (b) a full 1m cube? This determines whether or not to render the shared face of two 045 * adjacent blocks and also whether the player can attach torches, redstone wire, etc to this block. 046 */ 047 public boolean isOpaqueCube() 048 { 049 return false; 050 } 051 052 /** 053 * If this block doesn't render as an ordinary block it will return False (examples: signs, buttons, stairs, etc) 054 */ 055 public boolean renderAsNormalBlock() 056 { 057 return false; 058 } 059 060 /** 061 * The type of render function that is called for this block 062 */ 063 public int getRenderType() 064 { 065 return 5; 066 } 067 068 @SideOnly(Side.CLIENT) 069 070 /** 071 * Returns a integer with hex for 0xrrggbb with this color multiplied against the blocks color. Note only called 072 * when first determining what to render. 073 */ 074 public int colorMultiplier(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) 075 { 076 return 8388608; 077 } 078 079 /** 080 * Checks to see if its valid to put this block at the specified coordinates. Args: world, x, y, z 081 */ 082 public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4) 083 { 084 return par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4) || par1World.getBlockId(par2, par3 - 1, par4) == Block.glowStone.blockID; 085 } 086 087 /** 088 * Sets the strength of the wire current (0-15) for this block based on neighboring blocks and propagates to 089 * neighboring redstone wires 090 */ 091 private void updateAndPropagateCurrentStrength(World par1World, int par2, int par3, int par4) 092 { 093 this.calculateCurrentChanges(par1World, par2, par3, par4, par2, par3, par4); 094 ArrayList var5 = new ArrayList(this.blocksNeedingUpdate); 095 this.blocksNeedingUpdate.clear(); 096 Iterator var6 = var5.iterator(); 097 098 while (var6.hasNext()) 099 { 100 ChunkPosition var7 = (ChunkPosition)var6.next(); 101 par1World.notifyBlocksOfNeighborChange(var7.x, var7.y, var7.z, this.blockID); 102 } 103 } 104 105 private void calculateCurrentChanges(World par1World, int par2, int par3, int par4, int par5, int par6, int par7) 106 { 107 int var8 = par1World.getBlockMetadata(par2, par3, par4); 108 int var9 = 0; 109 this.wiresProvidePower = false; 110 boolean var10 = par1World.isBlockIndirectlyGettingPowered(par2, par3, par4); 111 this.wiresProvidePower = true; 112 int var11; 113 int var12; 114 int var13; 115 116 if (var10) 117 { 118 var9 = 15; 119 } 120 else 121 { 122 for (var11 = 0; var11 < 4; ++var11) 123 { 124 var12 = par2; 125 var13 = par4; 126 127 if (var11 == 0) 128 { 129 var12 = par2 - 1; 130 } 131 132 if (var11 == 1) 133 { 134 ++var12; 135 } 136 137 if (var11 == 2) 138 { 139 var13 = par4 - 1; 140 } 141 142 if (var11 == 3) 143 { 144 ++var13; 145 } 146 147 if (var12 != par5 || par3 != par6 || var13 != par7) 148 { 149 var9 = this.getMaxCurrentStrength(par1World, var12, par3, var13, var9); 150 } 151 152 if (par1World.isBlockNormalCube(var12, par3, var13) && !par1World.isBlockNormalCube(par2, par3 + 1, par4)) 153 { 154 if (var12 != par5 || par3 + 1 != par6 || var13 != par7) 155 { 156 var9 = this.getMaxCurrentStrength(par1World, var12, par3 + 1, var13, var9); 157 } 158 } 159 else if (!par1World.isBlockNormalCube(var12, par3, var13) && (var12 != par5 || par3 - 1 != par6 || var13 != par7)) 160 { 161 var9 = this.getMaxCurrentStrength(par1World, var12, par3 - 1, var13, var9); 162 } 163 } 164 165 if (var9 > 0) 166 { 167 --var9; 168 } 169 else 170 { 171 var9 = 0; 172 } 173 } 174 175 if (var8 != var9) 176 { 177 par1World.editingBlocks = true; 178 par1World.setBlockMetadataWithNotify(par2, par3, par4, var9); 179 par1World.markBlocksDirty(par2, par3, par4, par2, par3, par4); 180 par1World.editingBlocks = false; 181 182 for (var11 = 0; var11 < 4; ++var11) 183 { 184 var12 = par2; 185 var13 = par4; 186 int var14 = par3 - 1; 187 188 if (var11 == 0) 189 { 190 var12 = par2 - 1; 191 } 192 193 if (var11 == 1) 194 { 195 ++var12; 196 } 197 198 if (var11 == 2) 199 { 200 var13 = par4 - 1; 201 } 202 203 if (var11 == 3) 204 { 205 ++var13; 206 } 207 208 if (par1World.isBlockNormalCube(var12, par3, var13)) 209 { 210 var14 += 2; 211 } 212 213 boolean var15 = false; 214 int var16 = this.getMaxCurrentStrength(par1World, var12, par3, var13, -1); 215 var9 = par1World.getBlockMetadata(par2, par3, par4); 216 217 if (var9 > 0) 218 { 219 --var9; 220 } 221 222 if (var16 >= 0 && var16 != var9) 223 { 224 this.calculateCurrentChanges(par1World, var12, par3, var13, par2, par3, par4); 225 } 226 227 var16 = this.getMaxCurrentStrength(par1World, var12, var14, var13, -1); 228 var9 = par1World.getBlockMetadata(par2, par3, par4); 229 230 if (var9 > 0) 231 { 232 --var9; 233 } 234 235 if (var16 >= 0 && var16 != var9) 236 { 237 this.calculateCurrentChanges(par1World, var12, var14, var13, par2, par3, par4); 238 } 239 } 240 241 if (var8 < var9 || var9 == 0) 242 { 243 this.blocksNeedingUpdate.add(new ChunkPosition(par2, par3, par4)); 244 this.blocksNeedingUpdate.add(new ChunkPosition(par2 - 1, par3, par4)); 245 this.blocksNeedingUpdate.add(new ChunkPosition(par2 + 1, par3, par4)); 246 this.blocksNeedingUpdate.add(new ChunkPosition(par2, par3 - 1, par4)); 247 this.blocksNeedingUpdate.add(new ChunkPosition(par2, par3 + 1, par4)); 248 this.blocksNeedingUpdate.add(new ChunkPosition(par2, par3, par4 - 1)); 249 this.blocksNeedingUpdate.add(new ChunkPosition(par2, par3, par4 + 1)); 250 } 251 } 252 } 253 254 /** 255 * Calls World.notifyBlocksOfNeighborChange() for all neighboring blocks, but only if the given block is a redstone 256 * wire. 257 */ 258 private void notifyWireNeighborsOfNeighborChange(World par1World, int par2, int par3, int par4) 259 { 260 if (par1World.getBlockId(par2, par3, par4) == this.blockID) 261 { 262 par1World.notifyBlocksOfNeighborChange(par2, par3, par4, this.blockID); 263 par1World.notifyBlocksOfNeighborChange(par2 - 1, par3, par4, this.blockID); 264 par1World.notifyBlocksOfNeighborChange(par2 + 1, par3, par4, this.blockID); 265 par1World.notifyBlocksOfNeighborChange(par2, par3, par4 - 1, this.blockID); 266 par1World.notifyBlocksOfNeighborChange(par2, par3, par4 + 1, this.blockID); 267 par1World.notifyBlocksOfNeighborChange(par2, par3 - 1, par4, this.blockID); 268 par1World.notifyBlocksOfNeighborChange(par2, par3 + 1, par4, this.blockID); 269 } 270 } 271 272 /** 273 * Called whenever the block is added into the world. Args: world, x, y, z 274 */ 275 public void onBlockAdded(World par1World, int par2, int par3, int par4) 276 { 277 super.onBlockAdded(par1World, par2, par3, par4); 278 279 if (!par1World.isRemote) 280 { 281 this.updateAndPropagateCurrentStrength(par1World, par2, par3, par4); 282 par1World.notifyBlocksOfNeighborChange(par2, par3 + 1, par4, this.blockID); 283 par1World.notifyBlocksOfNeighborChange(par2, par3 - 1, par4, this.blockID); 284 this.notifyWireNeighborsOfNeighborChange(par1World, par2 - 1, par3, par4); 285 this.notifyWireNeighborsOfNeighborChange(par1World, par2 + 1, par3, par4); 286 this.notifyWireNeighborsOfNeighborChange(par1World, par2, par3, par4 - 1); 287 this.notifyWireNeighborsOfNeighborChange(par1World, par2, par3, par4 + 1); 288 289 if (par1World.isBlockNormalCube(par2 - 1, par3, par4)) 290 { 291 this.notifyWireNeighborsOfNeighborChange(par1World, par2 - 1, par3 + 1, par4); 292 } 293 else 294 { 295 this.notifyWireNeighborsOfNeighborChange(par1World, par2 - 1, par3 - 1, par4); 296 } 297 298 if (par1World.isBlockNormalCube(par2 + 1, par3, par4)) 299 { 300 this.notifyWireNeighborsOfNeighborChange(par1World, par2 + 1, par3 + 1, par4); 301 } 302 else 303 { 304 this.notifyWireNeighborsOfNeighborChange(par1World, par2 + 1, par3 - 1, par4); 305 } 306 307 if (par1World.isBlockNormalCube(par2, par3, par4 - 1)) 308 { 309 this.notifyWireNeighborsOfNeighborChange(par1World, par2, par3 + 1, par4 - 1); 310 } 311 else 312 { 313 this.notifyWireNeighborsOfNeighborChange(par1World, par2, par3 - 1, par4 - 1); 314 } 315 316 if (par1World.isBlockNormalCube(par2, par3, par4 + 1)) 317 { 318 this.notifyWireNeighborsOfNeighborChange(par1World, par2, par3 + 1, par4 + 1); 319 } 320 else 321 { 322 this.notifyWireNeighborsOfNeighborChange(par1World, par2, par3 - 1, par4 + 1); 323 } 324 } 325 } 326 327 /** 328 * ejects contained items into the world, and notifies neighbours of an update, as appropriate 329 */ 330 public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6) 331 { 332 super.breakBlock(par1World, par2, par3, par4, par5, par6); 333 334 if (!par1World.isRemote) 335 { 336 par1World.notifyBlocksOfNeighborChange(par2, par3 + 1, par4, this.blockID); 337 par1World.notifyBlocksOfNeighborChange(par2, par3 - 1, par4, this.blockID); 338 par1World.notifyBlocksOfNeighborChange(par2 + 1, par3, par4, this.blockID); 339 par1World.notifyBlocksOfNeighborChange(par2 - 1, par3, par4, this.blockID); 340 par1World.notifyBlocksOfNeighborChange(par2, par3, par4 + 1, this.blockID); 341 par1World.notifyBlocksOfNeighborChange(par2, par3, par4 - 1, this.blockID); 342 this.updateAndPropagateCurrentStrength(par1World, par2, par3, par4); 343 this.notifyWireNeighborsOfNeighborChange(par1World, par2 - 1, par3, par4); 344 this.notifyWireNeighborsOfNeighborChange(par1World, par2 + 1, par3, par4); 345 this.notifyWireNeighborsOfNeighborChange(par1World, par2, par3, par4 - 1); 346 this.notifyWireNeighborsOfNeighborChange(par1World, par2, par3, par4 + 1); 347 348 if (par1World.isBlockNormalCube(par2 - 1, par3, par4)) 349 { 350 this.notifyWireNeighborsOfNeighborChange(par1World, par2 - 1, par3 + 1, par4); 351 } 352 else 353 { 354 this.notifyWireNeighborsOfNeighborChange(par1World, par2 - 1, par3 - 1, par4); 355 } 356 357 if (par1World.isBlockNormalCube(par2 + 1, par3, par4)) 358 { 359 this.notifyWireNeighborsOfNeighborChange(par1World, par2 + 1, par3 + 1, par4); 360 } 361 else 362 { 363 this.notifyWireNeighborsOfNeighborChange(par1World, par2 + 1, par3 - 1, par4); 364 } 365 366 if (par1World.isBlockNormalCube(par2, par3, par4 - 1)) 367 { 368 this.notifyWireNeighborsOfNeighborChange(par1World, par2, par3 + 1, par4 - 1); 369 } 370 else 371 { 372 this.notifyWireNeighborsOfNeighborChange(par1World, par2, par3 - 1, par4 - 1); 373 } 374 375 if (par1World.isBlockNormalCube(par2, par3, par4 + 1)) 376 { 377 this.notifyWireNeighborsOfNeighborChange(par1World, par2, par3 + 1, par4 + 1); 378 } 379 else 380 { 381 this.notifyWireNeighborsOfNeighborChange(par1World, par2, par3 - 1, par4 + 1); 382 } 383 } 384 } 385 386 /** 387 * Returns the current strength at the specified block if it is greater than the passed value, or the passed value 388 * otherwise. Signature: (world, x, y, z, strength) 389 */ 390 private int getMaxCurrentStrength(World par1World, int par2, int par3, int par4, int par5) 391 { 392 if (par1World.getBlockId(par2, par3, par4) != this.blockID) 393 { 394 return par5; 395 } 396 else 397 { 398 int var6 = par1World.getBlockMetadata(par2, par3, par4); 399 return var6 > par5 ? var6 : par5; 400 } 401 } 402 403 /** 404 * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are 405 * their own) Args: x, y, z, neighbor blockID 406 */ 407 public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) 408 { 409 if (!par1World.isRemote) 410 { 411 int var6 = par1World.getBlockMetadata(par2, par3, par4); 412 boolean var7 = this.canPlaceBlockAt(par1World, par2, par3, par4); 413 414 if (var7) 415 { 416 this.updateAndPropagateCurrentStrength(par1World, par2, par3, par4); 417 } 418 else 419 { 420 this.dropBlockAsItem(par1World, par2, par3, par4, var6, 0); 421 par1World.setBlockWithNotify(par2, par3, par4, 0); 422 } 423 424 super.onNeighborBlockChange(par1World, par2, par3, par4, par5); 425 } 426 } 427 428 /** 429 * Returns the ID of the items to drop on destruction. 430 */ 431 public int idDropped(int par1, Random par2Random, int par3) 432 { 433 return Item.redstone.shiftedIndex; 434 } 435 436 /** 437 * Is this block indirectly powering the block on the specified side 438 */ 439 public boolean isIndirectlyPoweringTo(World par1World, int par2, int par3, int par4, int par5) 440 { 441 return !this.wiresProvidePower ? false : this.isPoweringTo(par1World, par2, par3, par4, par5); 442 } 443 444 /** 445 * Is this block powering the block on the specified side 446 */ 447 public boolean isPoweringTo(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) 448 { 449 if (!this.wiresProvidePower) 450 { 451 return false; 452 } 453 else if (par1IBlockAccess.getBlockMetadata(par2, par3, par4) == 0) 454 { 455 return false; 456 } 457 else if (par5 == 1) 458 { 459 return true; 460 } 461 else 462 { 463 boolean var6 = isPoweredOrRepeater(par1IBlockAccess, par2 - 1, par3, par4, 1) || !par1IBlockAccess.isBlockNormalCube(par2 - 1, par3, par4) && isPoweredOrRepeater(par1IBlockAccess, par2 - 1, par3 - 1, par4, -1); 464 boolean var7 = isPoweredOrRepeater(par1IBlockAccess, par2 + 1, par3, par4, 3) || !par1IBlockAccess.isBlockNormalCube(par2 + 1, par3, par4) && isPoweredOrRepeater(par1IBlockAccess, par2 + 1, par3 - 1, par4, -1); 465 boolean var8 = isPoweredOrRepeater(par1IBlockAccess, par2, par3, par4 - 1, 2) || !par1IBlockAccess.isBlockNormalCube(par2, par3, par4 - 1) && isPoweredOrRepeater(par1IBlockAccess, par2, par3 - 1, par4 - 1, -1); 466 boolean var9 = isPoweredOrRepeater(par1IBlockAccess, par2, par3, par4 + 1, 0) || !par1IBlockAccess.isBlockNormalCube(par2, par3, par4 + 1) && isPoweredOrRepeater(par1IBlockAccess, par2, par3 - 1, par4 + 1, -1); 467 468 if (!par1IBlockAccess.isBlockNormalCube(par2, par3 + 1, par4)) 469 { 470 if (par1IBlockAccess.isBlockNormalCube(par2 - 1, par3, par4) && isPoweredOrRepeater(par1IBlockAccess, par2 - 1, par3 + 1, par4, -1)) 471 { 472 var6 = true; 473 } 474 475 if (par1IBlockAccess.isBlockNormalCube(par2 + 1, par3, par4) && isPoweredOrRepeater(par1IBlockAccess, par2 + 1, par3 + 1, par4, -1)) 476 { 477 var7 = true; 478 } 479 480 if (par1IBlockAccess.isBlockNormalCube(par2, par3, par4 - 1) && isPoweredOrRepeater(par1IBlockAccess, par2, par3 + 1, par4 - 1, -1)) 481 { 482 var8 = true; 483 } 484 485 if (par1IBlockAccess.isBlockNormalCube(par2, par3, par4 + 1) && isPoweredOrRepeater(par1IBlockAccess, par2, par3 + 1, par4 + 1, -1)) 486 { 487 var9 = true; 488 } 489 } 490 491 return !var8 && !var7 && !var6 && !var9 && par5 >= 2 && par5 <= 5 ? true : (par5 == 2 && var8 && !var6 && !var7 ? true : (par5 == 3 && var9 && !var6 && !var7 ? true : (par5 == 4 && var6 && !var8 && !var9 ? true : par5 == 5 && var7 && !var8 && !var9))); 492 } 493 } 494 495 /** 496 * Can this block provide power. Only wire currently seems to have this change based on its state. 497 */ 498 public boolean canProvidePower() 499 { 500 return this.wiresProvidePower; 501 } 502 503 @SideOnly(Side.CLIENT) 504 505 /** 506 * A randomly called display update to be able to add particles or other items for display 507 */ 508 public void randomDisplayTick(World par1World, int par2, int par3, int par4, Random par5Random) 509 { 510 int var6 = par1World.getBlockMetadata(par2, par3, par4); 511 512 if (var6 > 0) 513 { 514 double var7 = (double)par2 + 0.5D + ((double)par5Random.nextFloat() - 0.5D) * 0.2D; 515 double var9 = (double)((float)par3 + 0.0625F); 516 double var11 = (double)par4 + 0.5D + ((double)par5Random.nextFloat() - 0.5D) * 0.2D; 517 float var13 = (float)var6 / 15.0F; 518 float var14 = var13 * 0.6F + 0.4F; 519 520 if (var6 == 0) 521 { 522 var14 = 0.0F; 523 } 524 525 float var15 = var13 * var13 * 0.7F - 0.5F; 526 float var16 = var13 * var13 * 0.6F - 0.7F; 527 528 if (var15 < 0.0F) 529 { 530 var15 = 0.0F; 531 } 532 533 if (var16 < 0.0F) 534 { 535 var16 = 0.0F; 536 } 537 538 par1World.spawnParticle("reddust", var7, var9, var11, (double)var14, (double)var15, (double)var16); 539 } 540 } 541 542 /** 543 * Returns true if the block coordinate passed can provide power, or is a redstone wire. 544 */ 545 public static boolean isPowerProviderOrWire(IBlockAccess par0IBlockAccess, int par1, int par2, int par3, int par4) 546 { 547 int var5 = par0IBlockAccess.getBlockId(par1, par2, par3); 548 549 if (var5 == Block.redstoneWire.blockID) 550 { 551 return true; 552 } 553 else if (var5 == 0) 554 { 555 return false; 556 } 557 else if (var5 != Block.redstoneRepeaterIdle.blockID && var5 != Block.redstoneRepeaterActive.blockID) 558 { 559 return (Block.blocksList[var5] != null && Block.blocksList[var5].canConnectRedstone(par0IBlockAccess, par1, par2, par3, par4)); 560 } 561 else 562 { 563 int var6 = par0IBlockAccess.getBlockMetadata(par1, par2, par3); 564 return par4 == (var6 & 3) || par4 == Direction.footInvisibleFaceRemap[var6 & 3]; 565 } 566 } 567 568 /** 569 * Returns true if the block coordinate passed can provide power, or is a redstone wire, or if its a repeater that 570 * is powered. 571 */ 572 public static boolean isPoweredOrRepeater(IBlockAccess par0IBlockAccess, int par1, int par2, int par3, int par4) 573 { 574 if (isPowerProviderOrWire(par0IBlockAccess, par1, par2, par3, par4)) 575 { 576 return true; 577 } 578 else 579 { 580 int var5 = par0IBlockAccess.getBlockId(par1, par2, par3); 581 582 if (var5 == Block.redstoneRepeaterActive.blockID) 583 { 584 int var6 = par0IBlockAccess.getBlockMetadata(par1, par2, par3); 585 return par4 == (var6 & 3); 586 } 587 else 588 { 589 return false; 590 } 591 } 592 } 593 594 @SideOnly(Side.CLIENT) 595 596 /** 597 * only called by clickMiddleMouseButton , and passed to inventory.setCurrentItem (along with isCreative) 598 */ 599 public int idPicked(World par1World, int par2, int par3, int par4) 600 { 601 return Item.redstone.shiftedIndex; 602 } 603 }