001 package net.minecraft.block; 002 003 import cpw.mods.fml.relauncher.Side; 004 import cpw.mods.fml.relauncher.SideOnly; 005 import java.util.Random; 006 import net.minecraft.block.material.Material; 007 import net.minecraft.entity.player.EntityPlayer; 008 import net.minecraft.item.Item; 009 import net.minecraft.util.AxisAlignedBB; 010 import net.minecraft.util.MovingObjectPosition; 011 import net.minecraft.util.Vec3; 012 import net.minecraft.world.IBlockAccess; 013 import net.minecraft.world.World; 014 015 public class BlockDoor extends Block 016 { 017 protected BlockDoor(int par1, Material par2Material) 018 { 019 super(par1, par2Material); 020 this.blockIndexInTexture = 97; 021 022 if (par2Material == Material.iron) 023 { 024 ++this.blockIndexInTexture; 025 } 026 027 float var3 = 0.5F; 028 float var4 = 1.0F; 029 this.setBlockBounds(0.5F - var3, 0.0F, 0.5F - var3, 0.5F + var3, var4, 0.5F + var3); 030 } 031 032 @SideOnly(Side.CLIENT) 033 034 /** 035 * Retrieves the block texture to use based on the display side. Args: iBlockAccess, x, y, z, side 036 */ 037 public int getBlockTexture(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) 038 { 039 if (par5 != 0 && par5 != 1) 040 { 041 int var6 = this.getFullMetadata(par1IBlockAccess, par2, par3, par4); 042 int var7 = this.blockIndexInTexture; 043 044 if ((var6 & 8) != 0) 045 { 046 var7 -= 16; 047 } 048 049 int var8 = var6 & 3; 050 boolean var9 = (var6 & 4) != 0; 051 052 if (var9) 053 { 054 if (var8 == 0 && par5 == 2) 055 { 056 var7 = -var7; 057 } 058 else if (var8 == 1 && par5 == 5) 059 { 060 var7 = -var7; 061 } 062 else if (var8 == 2 && par5 == 3) 063 { 064 var7 = -var7; 065 } 066 else if (var8 == 3 && par5 == 4) 067 { 068 var7 = -var7; 069 } 070 } 071 else 072 { 073 if (var8 == 0 && par5 == 5) 074 { 075 var7 = -var7; 076 } 077 else if (var8 == 1 && par5 == 3) 078 { 079 var7 = -var7; 080 } 081 else if (var8 == 2 && par5 == 4) 082 { 083 var7 = -var7; 084 } 085 else if (var8 == 3 && par5 == 2) 086 { 087 var7 = -var7; 088 } 089 090 if ((var6 & 16) != 0) 091 { 092 var7 = -var7; 093 } 094 } 095 096 return var7; 097 } 098 else 099 { 100 return this.blockIndexInTexture; 101 } 102 } 103 104 /** 105 * Is this block (a) opaque and (b) a full 1m cube? This determines whether or not to render the shared face of two 106 * adjacent blocks and also whether the player can attach torches, redstone wire, etc to this block. 107 */ 108 public boolean isOpaqueCube() 109 { 110 return false; 111 } 112 113 public boolean getBlocksMovement(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) 114 { 115 int var5 = this.getFullMetadata(par1IBlockAccess, par2, par3, par4); 116 return (var5 & 4) != 0; 117 } 118 119 /** 120 * If this block doesn't render as an ordinary block it will return False (examples: signs, buttons, stairs, etc) 121 */ 122 public boolean renderAsNormalBlock() 123 { 124 return false; 125 } 126 127 /** 128 * The type of render function that is called for this block 129 */ 130 public int getRenderType() 131 { 132 return 7; 133 } 134 135 @SideOnly(Side.CLIENT) 136 137 /** 138 * Returns the bounding box of the wired rectangular prism to render. 139 */ 140 public AxisAlignedBB getSelectedBoundingBoxFromPool(World par1World, int par2, int par3, int par4) 141 { 142 this.setBlockBoundsBasedOnState(par1World, par2, par3, par4); 143 return super.getSelectedBoundingBoxFromPool(par1World, par2, par3, par4); 144 } 145 146 /** 147 * Returns a bounding box from the pool of bounding boxes (this means this box can change after the pool has been 148 * cleared to be reused) 149 */ 150 public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4) 151 { 152 this.setBlockBoundsBasedOnState(par1World, par2, par3, par4); 153 return super.getCollisionBoundingBoxFromPool(par1World, par2, par3, par4); 154 } 155 156 /** 157 * Updates the blocks bounds based on its current state. Args: world, x, y, z 158 */ 159 public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) 160 { 161 this.setDoorRotation(this.getFullMetadata(par1IBlockAccess, par2, par3, par4)); 162 } 163 164 /** 165 * Returns 0, 1, 2 or 3 depending on where the hinge is. 166 */ 167 public int getDoorOrientation(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) 168 { 169 return this.getFullMetadata(par1IBlockAccess, par2, par3, par4) & 3; 170 } 171 172 public boolean isDoorOpen(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) 173 { 174 return (this.getFullMetadata(par1IBlockAccess, par2, par3, par4) & 4) != 0; 175 } 176 177 private void setDoorRotation(int par1) 178 { 179 float var2 = 0.1875F; 180 this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 2.0F, 1.0F); 181 int var3 = par1 & 3; 182 boolean var4 = (par1 & 4) != 0; 183 boolean var5 = (par1 & 16) != 0; 184 185 if (var3 == 0) 186 { 187 if (var4) 188 { 189 if (!var5) 190 { 191 this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, var2); 192 } 193 else 194 { 195 this.setBlockBounds(0.0F, 0.0F, 1.0F - var2, 1.0F, 1.0F, 1.0F); 196 } 197 } 198 else 199 { 200 this.setBlockBounds(0.0F, 0.0F, 0.0F, var2, 1.0F, 1.0F); 201 } 202 } 203 else if (var3 == 1) 204 { 205 if (var4) 206 { 207 if (!var5) 208 { 209 this.setBlockBounds(1.0F - var2, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F); 210 } 211 else 212 { 213 this.setBlockBounds(0.0F, 0.0F, 0.0F, var2, 1.0F, 1.0F); 214 } 215 } 216 else 217 { 218 this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, var2); 219 } 220 } 221 else if (var3 == 2) 222 { 223 if (var4) 224 { 225 if (!var5) 226 { 227 this.setBlockBounds(0.0F, 0.0F, 1.0F - var2, 1.0F, 1.0F, 1.0F); 228 } 229 else 230 { 231 this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, var2); 232 } 233 } 234 else 235 { 236 this.setBlockBounds(1.0F - var2, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F); 237 } 238 } 239 else if (var3 == 3) 240 { 241 if (var4) 242 { 243 if (!var5) 244 { 245 this.setBlockBounds(0.0F, 0.0F, 0.0F, var2, 1.0F, 1.0F); 246 } 247 else 248 { 249 this.setBlockBounds(1.0F - var2, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F); 250 } 251 } 252 else 253 { 254 this.setBlockBounds(0.0F, 0.0F, 1.0F - var2, 1.0F, 1.0F, 1.0F); 255 } 256 } 257 } 258 259 /** 260 * Called when the block is clicked by a player. Args: x, y, z, entityPlayer 261 */ 262 public void onBlockClicked(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer) {} 263 264 /** 265 * Called upon block activation (right click on the block.) 266 */ 267 public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9) 268 { 269 if (this.blockMaterial == Material.iron) 270 { 271 return false; //Allow items to interact with the door 272 } 273 else 274 { 275 int var10 = this.getFullMetadata(par1World, par2, par3, par4); 276 int var11 = var10 & 7; 277 var11 ^= 4; 278 279 if ((var10 & 8) == 0) 280 { 281 par1World.setBlockMetadataWithNotify(par2, par3, par4, var11); 282 par1World.markBlockRangeForRenderUpdate(par2, par3, par4, par2, par3, par4); 283 } 284 else 285 { 286 par1World.setBlockMetadataWithNotify(par2, par3 - 1, par4, var11); 287 par1World.markBlockRangeForRenderUpdate(par2, par3 - 1, par4, par2, par3, par4); 288 } 289 290 par1World.playAuxSFXAtEntity(par5EntityPlayer, 1003, par2, par3, par4, 0); 291 return true; 292 } 293 } 294 295 /** 296 * A function to open a door. 297 */ 298 public void onPoweredBlockChange(World par1World, int par2, int par3, int par4, boolean par5) 299 { 300 int var6 = this.getFullMetadata(par1World, par2, par3, par4); 301 boolean var7 = (var6 & 4) != 0; 302 303 if (var7 != par5) 304 { 305 int var8 = var6 & 7; 306 var8 ^= 4; 307 308 if ((var6 & 8) == 0) 309 { 310 par1World.setBlockMetadataWithNotify(par2, par3, par4, var8); 311 par1World.markBlockRangeForRenderUpdate(par2, par3, par4, par2, par3, par4); 312 } 313 else 314 { 315 par1World.setBlockMetadataWithNotify(par2, par3 - 1, par4, var8); 316 par1World.markBlockRangeForRenderUpdate(par2, par3 - 1, par4, par2, par3, par4); 317 } 318 319 par1World.playAuxSFXAtEntity((EntityPlayer)null, 1003, par2, par3, par4, 0); 320 } 321 } 322 323 /** 324 * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are 325 * their own) Args: x, y, z, neighbor blockID 326 */ 327 public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) 328 { 329 int var6 = par1World.getBlockMetadata(par2, par3, par4); 330 331 if ((var6 & 8) == 0) 332 { 333 boolean var7 = false; 334 335 if (par1World.getBlockId(par2, par3 + 1, par4) != this.blockID) 336 { 337 par1World.setBlockWithNotify(par2, par3, par4, 0); 338 var7 = true; 339 } 340 341 if (!par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4)) 342 { 343 par1World.setBlockWithNotify(par2, par3, par4, 0); 344 var7 = true; 345 346 if (par1World.getBlockId(par2, par3 + 1, par4) == this.blockID) 347 { 348 par1World.setBlockWithNotify(par2, par3 + 1, par4, 0); 349 } 350 } 351 352 if (var7) 353 { 354 if (!par1World.isRemote) 355 { 356 this.dropBlockAsItem(par1World, par2, par3, par4, var6, 0); 357 } 358 } 359 else 360 { 361 boolean var8 = par1World.isBlockIndirectlyGettingPowered(par2, par3, par4) || par1World.isBlockIndirectlyGettingPowered(par2, par3 + 1, par4); 362 363 if ((var8 || par5 > 0 && Block.blocksList[par5].canProvidePower()) && par5 != this.blockID) 364 { 365 this.onPoweredBlockChange(par1World, par2, par3, par4, var8); 366 } 367 } 368 } 369 else 370 { 371 if (par1World.getBlockId(par2, par3 - 1, par4) != this.blockID) 372 { 373 par1World.setBlockWithNotify(par2, par3, par4, 0); 374 } 375 376 if (par5 > 0 && par5 != this.blockID) 377 { 378 this.onNeighborBlockChange(par1World, par2, par3 - 1, par4, par5); 379 } 380 } 381 } 382 383 /** 384 * Returns the ID of the items to drop on destruction. 385 */ 386 public int idDropped(int par1, Random par2Random, int par3) 387 { 388 return (par1 & 8) != 0 ? 0 : (this.blockMaterial == Material.iron ? Item.doorSteel.itemID : Item.doorWood.itemID); 389 } 390 391 /** 392 * Ray traces through the blocks collision from start vector to end vector returning a ray trace hit. Args: world, 393 * x, y, z, startVec, endVec 394 */ 395 public MovingObjectPosition collisionRayTrace(World par1World, int par2, int par3, int par4, Vec3 par5Vec3, Vec3 par6Vec3) 396 { 397 this.setBlockBoundsBasedOnState(par1World, par2, par3, par4); 398 return super.collisionRayTrace(par1World, par2, par3, par4, par5Vec3, par6Vec3); 399 } 400 401 /** 402 * Checks to see if its valid to put this block at the specified coordinates. Args: world, x, y, z 403 */ 404 public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4) 405 { 406 return par3 >= 255 ? false : par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4) && super.canPlaceBlockAt(par1World, par2, par3, par4) && super.canPlaceBlockAt(par1World, par2, par3 + 1, par4); 407 } 408 409 /** 410 * Returns the mobility information of the block, 0 = free, 1 = can't push but can move over, 2 = total immobility 411 * and stop pistons 412 */ 413 public int getMobilityFlag() 414 { 415 return 1; 416 } 417 418 /** 419 * Returns the full metadata value created by combining the metadata of both blocks the door takes up. 420 */ 421 public int getFullMetadata(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) 422 { 423 int var5 = par1IBlockAccess.getBlockMetadata(par2, par3, par4); 424 boolean var6 = (var5 & 8) != 0; 425 int var7; 426 int var8; 427 428 if (var6) 429 { 430 var7 = par1IBlockAccess.getBlockMetadata(par2, par3 - 1, par4); 431 var8 = var5; 432 } 433 else 434 { 435 var7 = var5; 436 var8 = par1IBlockAccess.getBlockMetadata(par2, par3 + 1, par4); 437 } 438 439 boolean var9 = (var8 & 1) != 0; 440 return var7 & 7 | (var6 ? 8 : 0) | (var9 ? 16 : 0); 441 } 442 443 @SideOnly(Side.CLIENT) 444 445 /** 446 * only called by clickMiddleMouseButton , and passed to inventory.setCurrentItem (along with isCreative) 447 */ 448 public int idPicked(World par1World, int par2, int par3, int par4) 449 { 450 return this.blockMaterial == Material.iron ? Item.doorSteel.itemID : Item.doorWood.itemID; 451 } 452 453 /** 454 * Called when the block is attempted to be harvested 455 */ 456 public void onBlockHarvested(World par1World, int par2, int par3, int par4, int par5, EntityPlayer par6EntityPlayer) 457 { 458 if (par6EntityPlayer.capabilities.isCreativeMode && (par5 & 8) != 0 && par1World.getBlockId(par2, par3 - 1, par4) == this.blockID) 459 { 460 par1World.setBlockWithNotify(par2, par3 - 1, par4, 0); 461 } 462 } 463 }