001 package net.minecraft.src; 002 003 import java.util.List; 004 import java.util.Random; 005 006 import net.minecraftforge.common.ForgeDirection; 007 008 import static net.minecraftforge.common.ForgeDirection.*; 009 010 public class BlockButton extends Block 011 { 012 /** Whether this button is sensible to arrows, used by wooden buttons. */ 013 private final boolean sensible; 014 015 protected BlockButton(int par1, int par2, boolean par3) 016 { 017 super(par1, par2, Material.circuits); 018 this.setTickRandomly(true); 019 this.setCreativeTab(CreativeTabs.tabRedstone); 020 this.sensible = par3; 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 * How many world ticks before ticking 034 */ 035 public int tickRate() 036 { 037 return this.sensible ? 30 : 20; 038 } 039 040 /** 041 * Is this block (a) opaque and (b) a full 1m cube? This determines whether or not to render the shared face of two 042 * adjacent blocks and also whether the player can attach torches, redstone wire, etc to this block. 043 */ 044 public boolean isOpaqueCube() 045 { 046 return false; 047 } 048 049 /** 050 * If this block doesn't render as an ordinary block it will return False (examples: signs, buttons, stairs, etc) 051 */ 052 public boolean renderAsNormalBlock() 053 { 054 return false; 055 } 056 057 /** 058 * checks to see if you can place this block can be placed on that side of a block: BlockLever overrides 059 */ 060 public boolean canPlaceBlockOnSide(World par1World, int par2, int par3, int par4, int par5) 061 { 062 ForgeDirection dir = ForgeDirection.getOrientation(par5); 063 return (dir == NORTH && par1World.isBlockSolidOnSide(par2, par3, par4 + 1, NORTH)) || 064 (dir == SOUTH && par1World.isBlockSolidOnSide(par2, par3, par4 - 1, SOUTH)) || 065 (dir == WEST && par1World.isBlockSolidOnSide(par2 + 1, par3, par4, WEST)) || 066 (dir == EAST && par1World.isBlockSolidOnSide(par2 - 1, par3, par4, EAST)); 067 } 068 069 /** 070 * Checks to see if its valid to put this block at the specified coordinates. Args: world, x, y, z 071 */ 072 public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4) 073 { 074 return (par1World.isBlockSolidOnSide(par2 - 1, par3, par4, EAST)) || 075 (par1World.isBlockSolidOnSide(par2 + 1, par3, par4, WEST)) || 076 (par1World.isBlockSolidOnSide(par2, par3, par4 - 1, SOUTH)) || 077 (par1World.isBlockSolidOnSide(par2, par3, par4 + 1, NORTH)); 078 } 079 080 /** 081 * called before onBlockPlacedBy by ItemBlock and ItemReed 082 */ 083 public void updateBlockMetadata(World par1World, int par2, int par3, int par4, int par5, float par6, float par7, float par8) 084 { 085 int var9 = par1World.getBlockMetadata(par2, par3, par4); 086 int var10 = var9 & 8; 087 var9 &= 7; 088 089 ForgeDirection dir = ForgeDirection.getOrientation(par5); 090 091 if (dir == NORTH && par1World.isBlockSolidOnSide(par2, par3, par4 + 1, NORTH)) 092 { 093 var9 = 4; 094 } 095 else if (dir == SOUTH && par1World.isBlockSolidOnSide(par2, par3, par4 - 1, SOUTH)) 096 { 097 var9 = 3; 098 } 099 else if (dir == WEST && par1World.isBlockSolidOnSide(par2 + 1, par3, par4, WEST)) 100 { 101 var9 = 2; 102 } 103 else if (dir == EAST && par1World.isBlockSolidOnSide(par2 - 1, par3, par4, EAST)) 104 { 105 var9 = 1; 106 } 107 else 108 { 109 var9 = this.getOrientation(par1World, par2, par3, par4); 110 } 111 112 par1World.setBlockMetadataWithNotify(par2, par3, par4, var9 + var10); 113 } 114 115 /** 116 * Get side which this button is facing. 117 */ 118 private int getOrientation(World par1World, int par2, int par3, int par4) 119 { 120 if (par1World.isBlockSolidOnSide(par2 - 1, par3, par4, EAST)) return 1; 121 if (par1World.isBlockSolidOnSide(par2 + 1, par3, par4, WEST)) return 2; 122 if (par1World.isBlockSolidOnSide(par2, par3, par4 - 1, SOUTH)) return 3; 123 if (par1World.isBlockSolidOnSide(par2, par3, par4 + 1, NORTH)) return 4; 124 return 1; 125 } 126 127 /** 128 * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are 129 * their own) Args: x, y, z, neighbor blockID 130 */ 131 public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) 132 { 133 if (this.redundantCanPlaceBlockAt(par1World, par2, par3, par4)) 134 { 135 int var6 = par1World.getBlockMetadata(par2, par3, par4) & 7; 136 boolean var7 = false; 137 138 if (!par1World.isBlockSolidOnSide(par2 - 1, par3, par4, EAST) && var6 == 1) 139 { 140 var7 = true; 141 } 142 143 if (!par1World.isBlockSolidOnSide(par2 + 1, par3, par4, WEST) && var6 == 2) 144 { 145 var7 = true; 146 } 147 148 if (!par1World.isBlockSolidOnSide(par2, par3, par4 - 1, SOUTH) && var6 == 3) 149 { 150 var7 = true; 151 } 152 153 if (!par1World.isBlockSolidOnSide(par2, par3, par4 + 1, NORTH) && var6 == 4) 154 { 155 var7 = true; 156 } 157 158 if (var7) 159 { 160 this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0); 161 par1World.setBlockWithNotify(par2, par3, par4, 0); 162 } 163 } 164 } 165 166 /** 167 * This method is redundant, check it out... 168 */ 169 private boolean redundantCanPlaceBlockAt(World par1World, int par2, int par3, int par4) 170 { 171 if (!this.canPlaceBlockAt(par1World, par2, par3, par4)) 172 { 173 this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0); 174 par1World.setBlockWithNotify(par2, par3, par4, 0); 175 return false; 176 } 177 else 178 { 179 return true; 180 } 181 } 182 183 /** 184 * Updates the blocks bounds based on its current state. Args: world, x, y, z 185 */ 186 public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) 187 { 188 int var5 = par1IBlockAccess.getBlockMetadata(par2, par3, par4); 189 this.func_82534_e(var5); 190 } 191 192 private void func_82534_e(int par1) 193 { 194 int var2 = par1 & 7; 195 boolean var3 = (par1 & 8) > 0; 196 float var4 = 0.375F; 197 float var5 = 0.625F; 198 float var6 = 0.1875F; 199 float var7 = 0.125F; 200 201 if (var3) 202 { 203 var7 = 0.0625F; 204 } 205 206 if (var2 == 1) 207 { 208 this.setBlockBounds(0.0F, var4, 0.5F - var6, var7, var5, 0.5F + var6); 209 } 210 else if (var2 == 2) 211 { 212 this.setBlockBounds(1.0F - var7, var4, 0.5F - var6, 1.0F, var5, 0.5F + var6); 213 } 214 else if (var2 == 3) 215 { 216 this.setBlockBounds(0.5F - var6, var4, 0.0F, 0.5F + var6, var5, var7); 217 } 218 else if (var2 == 4) 219 { 220 this.setBlockBounds(0.5F - var6, var4, 1.0F - var7, 0.5F + var6, var5, 1.0F); 221 } 222 } 223 224 /** 225 * Called when the block is clicked by a player. Args: x, y, z, entityPlayer 226 */ 227 public void onBlockClicked(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer) {} 228 229 /** 230 * Called upon block activation (right click on the block.) 231 */ 232 public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9) 233 { 234 int var10 = par1World.getBlockMetadata(par2, par3, par4); 235 int var11 = var10 & 7; 236 int var12 = 8 - (var10 & 8); 237 238 if (var12 == 0) 239 { 240 return true; 241 } 242 else 243 { 244 par1World.setBlockMetadataWithNotify(par2, par3, par4, var11 + var12); 245 par1World.markBlocksDirty(par2, par3, par4, par2, par3, par4); 246 par1World.playSoundEffect((double)par2 + 0.5D, (double)par3 + 0.5D, (double)par4 + 0.5D, "random.click", 0.3F, 0.6F); 247 this.func_82536_d(par1World, par2, par3, par4, var11); 248 par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, this.tickRate()); 249 return true; 250 } 251 } 252 253 /** 254 * ejects contained items into the world, and notifies neighbours of an update, as appropriate 255 */ 256 public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6) 257 { 258 if ((par6 & 8) > 0) 259 { 260 int var7 = par6 & 7; 261 this.func_82536_d(par1World, par2, par3, par4, var7); 262 } 263 264 super.breakBlock(par1World, par2, par3, par4, par5, par6); 265 } 266 267 /** 268 * Is this block powering the block on the specified side 269 */ 270 public boolean isPoweringTo(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) 271 { 272 return (par1IBlockAccess.getBlockMetadata(par2, par3, par4) & 8) > 0; 273 } 274 275 /** 276 * Is this block indirectly powering the block on the specified side 277 */ 278 public boolean isIndirectlyPoweringTo(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) 279 { 280 int var6 = par1IBlockAccess.getBlockMetadata(par2, par3, par4); 281 282 if ((var6 & 8) == 0) 283 { 284 return false; 285 } 286 else 287 { 288 int var7 = var6 & 7; 289 return var7 == 5 && par5 == 1 ? true : (var7 == 4 && par5 == 2 ? true : (var7 == 3 && par5 == 3 ? true : (var7 == 2 && par5 == 4 ? true : var7 == 1 && par5 == 5))); 290 } 291 } 292 293 /** 294 * Can this block provide power. Only wire currently seems to have this change based on its state. 295 */ 296 public boolean canProvidePower() 297 { 298 return true; 299 } 300 301 /** 302 * Ticks the block if it's been scheduled 303 */ 304 public void updateTick(World par1World, int par2, int par3, int par4, Random par5Random) 305 { 306 if (!par1World.isRemote) 307 { 308 int var6 = par1World.getBlockMetadata(par2, par3, par4); 309 310 if ((var6 & 8) != 0) 311 { 312 if (this.sensible) 313 { 314 this.func_82535_o(par1World, par2, par3, par4); 315 } 316 else 317 { 318 par1World.setBlockMetadataWithNotify(par2, par3, par4, var6 & 7); 319 int var7 = var6 & 7; 320 this.func_82536_d(par1World, par2, par3, par4, var7); 321 par1World.playSoundEffect((double)par2 + 0.5D, (double)par3 + 0.5D, (double)par4 + 0.5D, "random.click", 0.3F, 0.5F); 322 par1World.markBlocksDirty(par2, par3, par4, par2, par3, par4); 323 } 324 } 325 } 326 } 327 328 /** 329 * Sets the block's bounds for rendering it as an item 330 */ 331 public void setBlockBoundsForItemRender() 332 { 333 float var1 = 0.1875F; 334 float var2 = 0.125F; 335 float var3 = 0.125F; 336 this.setBlockBounds(0.5F - var1, 0.5F - var2, 0.5F - var3, 0.5F + var1, 0.5F + var2, 0.5F + var3); 337 } 338 339 /** 340 * Triggered whenever an entity collides with this block (enters into the block). Args: world, x, y, z, entity 341 */ 342 public void onEntityCollidedWithBlock(World par1World, int par2, int par3, int par4, Entity par5Entity) 343 { 344 if (!par1World.isRemote) 345 { 346 if (this.sensible) 347 { 348 if ((par1World.getBlockMetadata(par2, par3, par4) & 8) == 0) 349 { 350 this.func_82535_o(par1World, par2, par3, par4); 351 } 352 } 353 } 354 } 355 356 private void func_82535_o(World par1World, int par2, int par3, int par4) 357 { 358 int var5 = par1World.getBlockMetadata(par2, par3, par4); 359 int var6 = var5 & 7; 360 boolean var7 = (var5 & 8) != 0; 361 this.func_82534_e(var5); 362 List var9 = par1World.getEntitiesWithinAABB(EntityArrow.class, AxisAlignedBB.getAABBPool().addOrModifyAABBInPool((double)par2 + this.minX, (double)par3 + this.minY, (double)par4 + this.minZ, (double)par2 + this.maxX, (double)par3 + this.maxY, (double)par4 + this.maxZ)); 363 boolean var8 = !var9.isEmpty(); 364 365 if (var8 && !var7) 366 { 367 par1World.setBlockMetadataWithNotify(par2, par3, par4, var6 | 8); 368 this.func_82536_d(par1World, par2, par3, par4, var6); 369 par1World.markBlocksDirty(par2, par3, par4, par2, par3, par4); 370 par1World.playSoundEffect((double)par2 + 0.5D, (double)par3 + 0.5D, (double)par4 + 0.5D, "random.click", 0.3F, 0.6F); 371 } 372 373 if (!var8 && var7) 374 { 375 par1World.setBlockMetadataWithNotify(par2, par3, par4, var6); 376 this.func_82536_d(par1World, par2, par3, par4, var6); 377 par1World.markBlocksDirty(par2, par3, par4, par2, par3, par4); 378 par1World.playSoundEffect((double)par2 + 0.5D, (double)par3 + 0.5D, (double)par4 + 0.5D, "random.click", 0.3F, 0.5F); 379 } 380 381 if (var8) 382 { 383 par1World.scheduleBlockUpdate(par2, par3, par4, this.blockID, this.tickRate()); 384 } 385 } 386 387 private void func_82536_d(World par1World, int par2, int par3, int par4, int par5) 388 { 389 par1World.notifyBlocksOfNeighborChange(par2, par3, par4, this.blockID); 390 391 if (par5 == 1) 392 { 393 par1World.notifyBlocksOfNeighborChange(par2 - 1, par3, par4, this.blockID); 394 } 395 else if (par5 == 2) 396 { 397 par1World.notifyBlocksOfNeighborChange(par2 + 1, par3, par4, this.blockID); 398 } 399 else if (par5 == 3) 400 { 401 par1World.notifyBlocksOfNeighborChange(par2, par3, par4 - 1, this.blockID); 402 } 403 else if (par5 == 4) 404 { 405 par1World.notifyBlocksOfNeighborChange(par2, par3, par4 + 1, this.blockID); 406 } 407 else 408 { 409 par1World.notifyBlocksOfNeighborChange(par2, par3 - 1, par4, this.blockID); 410 } 411 } 412 }