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