001 package net.minecraft.block; 002 003 import net.minecraft.block.material.Material; 004 import net.minecraft.creativetab.CreativeTabs; 005 import net.minecraft.entity.player.EntityPlayer; 006 import net.minecraft.util.AxisAlignedBB; 007 import net.minecraft.world.IBlockAccess; 008 import net.minecraft.world.World; 009 010 import net.minecraftforge.common.ForgeDirection; 011 import static net.minecraftforge.common.ForgeDirection.*; 012 013 public class BlockLever extends Block 014 { 015 protected BlockLever(int par1, int par2) 016 { 017 super(par1, par2, Material.circuits); 018 this.setCreativeTab(CreativeTabs.tabRedstone); 019 } 020 021 /** 022 * Returns a bounding box from the pool of bounding boxes (this means this box can change after the pool has been 023 * cleared to be reused) 024 */ 025 public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4) 026 { 027 return null; 028 } 029 030 /** 031 * Is this block (a) opaque and (b) a full 1m cube? This determines whether or not to render the shared face of two 032 * adjacent blocks and also whether the player can attach torches, redstone wire, etc to this block. 033 */ 034 public boolean isOpaqueCube() 035 { 036 return false; 037 } 038 039 /** 040 * If this block doesn't render as an ordinary block it will return False (examples: signs, buttons, stairs, etc) 041 */ 042 public boolean renderAsNormalBlock() 043 { 044 return false; 045 } 046 047 /** 048 * The type of render function that is called for this block 049 */ 050 public int getRenderType() 051 { 052 return 12; 053 } 054 055 /** 056 * checks to see if you can place this block can be placed on that side of a block: BlockLever overrides 057 */ 058 public boolean canPlaceBlockOnSide(World par1World, int par2, int par3, int par4, int par5) 059 { 060 ForgeDirection dir = ForgeDirection.getOrientation(par5); 061 return (dir == DOWN && par1World.isBlockSolidOnSide(par2, par3 + 1, par4, DOWN )) || 062 (dir == UP && par1World.isBlockSolidOnSide(par2, par3 - 1, par4, UP )) || 063 (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 par1World.isBlockSolidOnSide(par2, par3 - 1, par4, UP ) || 079 par1World.isBlockSolidOnSide(par2, par3 + 1, par4, DOWN ); 080 } 081 082 /** 083 * Called when a block is placed using its ItemBlock. Args: World, X, Y, Z, side, hitX, hitY, hitZ, block metadata 084 */ 085 public int onBlockPlaced(World par1World, int par2, int par3, int par4, int par5, float par6, float par7, float par8, int par9) 086 { 087 int var11 = par9 & 8; 088 int var10 = par9 & 7; 089 var10 = -1; 090 091 if (par5 == 0 && par1World.isBlockSolidOnSide(par2, par3 + 1, par4, DOWN)) 092 { 093 var10 = par1World.rand.nextBoolean() ? 0 : 7; 094 } 095 096 if (par5 == 1 && par1World.isBlockSolidOnSide(par2, par3 - 1, par4, UP)) 097 { 098 var10 = 5 + par1World.rand.nextInt(2); 099 } 100 101 if (par5 == 2 && par1World.isBlockSolidOnSide(par2, par3, par4 + 1, NORTH)) 102 { 103 var10 = 4; 104 } 105 106 if (par5 == 3 && par1World.isBlockSolidOnSide(par2, par3, par4 - 1, SOUTH)) 107 { 108 var10 = 3; 109 } 110 111 if (par5 == 4 && par1World.isBlockSolidOnSide(par2 + 1, par3, par4, WEST)) 112 { 113 var10 = 2; 114 } 115 116 if (par5 == 5 && par1World.isBlockSolidOnSide(par2 - 1, par3, par4, EAST)) 117 { 118 var10 = 1; 119 } 120 121 return var10 + var11; 122 } 123 124 /** 125 * only used in ComponentScatteredFeatureJunglePyramid.addComponentParts" 126 */ 127 public static int invertMetadata(int par0) 128 { 129 switch (par0) 130 { 131 case 0: 132 return 0; 133 case 1: 134 return 5; 135 case 2: 136 return 4; 137 case 3: 138 return 3; 139 case 4: 140 return 2; 141 case 5: 142 return 1; 143 default: 144 return -1; 145 } 146 } 147 148 /** 149 * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are 150 * their own) Args: x, y, z, neighbor blockID 151 */ 152 public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) 153 { 154 if (this.checkIfAttachedToBlock(par1World, par2, par3, par4)) 155 { 156 int var6 = par1World.getBlockMetadata(par2, par3, par4) & 7; 157 boolean var7 = false; 158 159 if (!par1World.isBlockSolidOnSide(par2 - 1, par3, par4, EAST) && var6 == 1) 160 { 161 var7 = true; 162 } 163 164 if (!par1World.isBlockSolidOnSide(par2 + 1, par3, par4, WEST) && var6 == 2) 165 { 166 var7 = true; 167 } 168 169 if (!par1World.isBlockSolidOnSide(par2, par3, par4 - 1, SOUTH) && var6 == 3) 170 { 171 var7 = true; 172 } 173 174 if (!par1World.isBlockSolidOnSide(par2, par3, par4 + 1, NORTH) && var6 == 4) 175 { 176 var7 = true; 177 } 178 179 if (!par1World.isBlockSolidOnSide(par2, par3 - 1, par4, UP) && var6 == 5) 180 { 181 var7 = true; 182 } 183 184 if (!par1World.isBlockSolidOnSide(par2, par3 - 1, par4, UP) && var6 == 6) 185 { 186 var7 = true; 187 } 188 189 if (!par1World.isBlockSolidOnSide(par2, par3 + 1, par4, DOWN) && var6 == 0) 190 { 191 var7 = true; 192 } 193 194 if (!par1World.isBlockSolidOnSide(par2, par3 + 1, par4, DOWN) && var6 == 7) 195 { 196 var7 = true; 197 } 198 199 if (var7) 200 { 201 this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0); 202 par1World.setBlockWithNotify(par2, par3, par4, 0); 203 } 204 } 205 } 206 207 /** 208 * Checks if the block is attached to another block. If it is not, it returns false and drops the block as an item. 209 * If it is it returns true. 210 */ 211 private boolean checkIfAttachedToBlock(World par1World, int par2, int par3, int par4) 212 { 213 if (!this.canPlaceBlockAt(par1World, par2, par3, par4)) 214 { 215 this.dropBlockAsItem(par1World, par2, par3, par4, par1World.getBlockMetadata(par2, par3, par4), 0); 216 par1World.setBlockWithNotify(par2, par3, par4, 0); 217 return false; 218 } 219 else 220 { 221 return true; 222 } 223 } 224 225 /** 226 * Updates the blocks bounds based on its current state. Args: world, x, y, z 227 */ 228 public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) 229 { 230 int var5 = par1IBlockAccess.getBlockMetadata(par2, par3, par4) & 7; 231 float var6 = 0.1875F; 232 233 if (var5 == 1) 234 { 235 this.setBlockBounds(0.0F, 0.2F, 0.5F - var6, var6 * 2.0F, 0.8F, 0.5F + var6); 236 } 237 else if (var5 == 2) 238 { 239 this.setBlockBounds(1.0F - var6 * 2.0F, 0.2F, 0.5F - var6, 1.0F, 0.8F, 0.5F + var6); 240 } 241 else if (var5 == 3) 242 { 243 this.setBlockBounds(0.5F - var6, 0.2F, 0.0F, 0.5F + var6, 0.8F, var6 * 2.0F); 244 } 245 else if (var5 == 4) 246 { 247 this.setBlockBounds(0.5F - var6, 0.2F, 1.0F - var6 * 2.0F, 0.5F + var6, 0.8F, 1.0F); 248 } 249 else if (var5 != 5 && var5 != 6) 250 { 251 if (var5 == 0 || var5 == 7) 252 { 253 var6 = 0.25F; 254 this.setBlockBounds(0.5F - var6, 0.4F, 0.5F - var6, 0.5F + var6, 1.0F, 0.5F + var6); 255 } 256 } 257 else 258 { 259 var6 = 0.25F; 260 this.setBlockBounds(0.5F - var6, 0.0F, 0.5F - var6, 0.5F + var6, 0.6F, 0.5F + var6); 261 } 262 } 263 264 /** 265 * Called when the block is clicked by a player. Args: x, y, z, entityPlayer 266 */ 267 public void onBlockClicked(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer) {} 268 269 /** 270 * Called upon block activation (right click on the block.) 271 */ 272 public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9) 273 { 274 if (par1World.isRemote) 275 { 276 return true; 277 } 278 else 279 { 280 int var10 = par1World.getBlockMetadata(par2, par3, par4); 281 int var11 = var10 & 7; 282 int var12 = 8 - (var10 & 8); 283 par1World.setBlockMetadataWithNotify(par2, par3, par4, var11 + var12); 284 par1World.markBlockRangeForRenderUpdate(par2, par3, par4, par2, par3, par4); 285 par1World.playSoundEffect((double)par2 + 0.5D, (double)par3 + 0.5D, (double)par4 + 0.5D, "random.click", 0.3F, var12 > 0 ? 0.6F : 0.5F); 286 par1World.notifyBlocksOfNeighborChange(par2, par3, par4, this.blockID); 287 288 if (var11 == 1) 289 { 290 par1World.notifyBlocksOfNeighborChange(par2 - 1, par3, par4, this.blockID); 291 } 292 else if (var11 == 2) 293 { 294 par1World.notifyBlocksOfNeighborChange(par2 + 1, par3, par4, this.blockID); 295 } 296 else if (var11 == 3) 297 { 298 par1World.notifyBlocksOfNeighborChange(par2, par3, par4 - 1, this.blockID); 299 } 300 else if (var11 == 4) 301 { 302 par1World.notifyBlocksOfNeighborChange(par2, par3, par4 + 1, this.blockID); 303 } 304 else if (var11 != 5 && var11 != 6) 305 { 306 if (var11 == 0 || var11 == 7) 307 { 308 par1World.notifyBlocksOfNeighborChange(par2, par3 + 1, par4, this.blockID); 309 } 310 } 311 else 312 { 313 par1World.notifyBlocksOfNeighborChange(par2, par3 - 1, par4, this.blockID); 314 } 315 316 return true; 317 } 318 } 319 320 /** 321 * ejects contained items into the world, and notifies neighbours of an update, as appropriate 322 */ 323 public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6) 324 { 325 if ((par6 & 8) > 0) 326 { 327 par1World.notifyBlocksOfNeighborChange(par2, par3, par4, this.blockID); 328 int var7 = par6 & 7; 329 330 if (var7 == 1) 331 { 332 par1World.notifyBlocksOfNeighborChange(par2 - 1, par3, par4, this.blockID); 333 } 334 else if (var7 == 2) 335 { 336 par1World.notifyBlocksOfNeighborChange(par2 + 1, par3, par4, this.blockID); 337 } 338 else if (var7 == 3) 339 { 340 par1World.notifyBlocksOfNeighborChange(par2, par3, par4 - 1, this.blockID); 341 } 342 else if (var7 == 4) 343 { 344 par1World.notifyBlocksOfNeighborChange(par2, par3, par4 + 1, this.blockID); 345 } 346 else if (var7 != 5 && var7 != 6) 347 { 348 if (var7 == 0 || var7 == 7) 349 { 350 par1World.notifyBlocksOfNeighborChange(par2, par3 + 1, par4, this.blockID); 351 } 352 } 353 else 354 { 355 par1World.notifyBlocksOfNeighborChange(par2, par3 - 1, par4, this.blockID); 356 } 357 } 358 359 super.breakBlock(par1World, par2, par3, par4, par5, par6); 360 } 361 362 /** 363 * Returns true if the block is emitting indirect/weak redstone power on the specified side. If isBlockNormalCube 364 * returns true, standard redstone propagation rules will apply instead and this will not be called. Args: World, X, 365 * Y, Z, side. Note that the side is reversed - eg it is 1 (up) when checking the bottom of the block. 366 */ 367 public boolean isProvidingWeakPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) 368 { 369 return (par1IBlockAccess.getBlockMetadata(par2, par3, par4) & 8) > 0; 370 } 371 372 /** 373 * Returns true if the block is emitting direct/strong redstone power on the specified side. Args: World, X, Y, Z, 374 * side. Note that the side is reversed - eg it is 1 (up) when checking the bottom of the block. 375 */ 376 public boolean isProvidingStrongPower(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) 377 { 378 int var6 = par1IBlockAccess.getBlockMetadata(par2, par3, par4); 379 380 if ((var6 & 8) == 0) 381 { 382 return false; 383 } 384 else 385 { 386 int var7 = var6 & 7; 387 return var7 == 0 && par5 == 0 ? true : (var7 == 7 && par5 == 0 ? true : (var7 == 6 && par5 == 1 ? true : (var7 == 5 && par5 == 1 ? true : (var7 == 4 && par5 == 2 ? true : (var7 == 3 && par5 == 3 ? true : (var7 == 2 && par5 == 4 ? true : var7 == 1 && par5 == 5)))))); 388 } 389 } 390 391 /** 392 * Can this block provide power. Only wire currently seems to have this change based on its state. 393 */ 394 public boolean canProvidePower() 395 { 396 return true; 397 } 398 }