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