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 /** 258 * Called upon block activation (right click on the block.) 259 */ 260 public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9) 261 { 262 if (this.blockMaterial == Material.iron) 263 { 264 return false; //Allow items to interact with the door 265 } 266 else 267 { 268 int var10 = this.getFullMetadata(par1World, par2, par3, par4); 269 int var11 = var10 & 7; 270 var11 ^= 4; 271 272 if ((var10 & 8) == 0) 273 { 274 par1World.setBlockMetadataWithNotify(par2, par3, par4, var11); 275 par1World.markBlocksDirty(par2, par3, par4, par2, par3, par4); 276 } 277 else 278 { 279 par1World.setBlockMetadataWithNotify(par2, par3 - 1, par4, var11); 280 par1World.markBlocksDirty(par2, par3 - 1, par4, par2, par3, par4); 281 } 282 283 par1World.playAuxSFXAtEntity(par5EntityPlayer, 1003, par2, par3, par4, 0); 284 return true; 285 } 286 } 287 288 /** 289 * A function to open a door. 290 */ 291 public void onPoweredBlockChange(World par1World, int par2, int par3, int par4, boolean par5) 292 { 293 int var6 = this.getFullMetadata(par1World, par2, par3, par4); 294 boolean var7 = (var6 & 4) != 0; 295 296 if (var7 != par5) 297 { 298 int var8 = var6 & 7; 299 var8 ^= 4; 300 301 if ((var6 & 8) == 0) 302 { 303 par1World.setBlockMetadataWithNotify(par2, par3, par4, var8); 304 par1World.markBlocksDirty(par2, par3, par4, par2, par3, par4); 305 } 306 else 307 { 308 par1World.setBlockMetadataWithNotify(par2, par3 - 1, par4, var8); 309 par1World.markBlocksDirty(par2, par3 - 1, par4, par2, par3, par4); 310 } 311 312 par1World.playAuxSFXAtEntity((EntityPlayer)null, 1003, par2, par3, par4, 0); 313 } 314 } 315 316 /** 317 * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are 318 * their own) Args: x, y, z, neighbor blockID 319 */ 320 public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) 321 { 322 int var6 = par1World.getBlockMetadata(par2, par3, par4); 323 324 if ((var6 & 8) == 0) 325 { 326 boolean var7 = false; 327 328 if (par1World.getBlockId(par2, par3 + 1, par4) != this.blockID) 329 { 330 par1World.setBlockWithNotify(par2, par3, par4, 0); 331 var7 = true; 332 } 333 334 if (!par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4)) 335 { 336 par1World.setBlockWithNotify(par2, par3, par4, 0); 337 var7 = true; 338 339 if (par1World.getBlockId(par2, par3 + 1, par4) == this.blockID) 340 { 341 par1World.setBlockWithNotify(par2, par3 + 1, par4, 0); 342 } 343 } 344 345 if (var7) 346 { 347 if (!par1World.isRemote) 348 { 349 this.dropBlockAsItem(par1World, par2, par3, par4, var6, 0); 350 } 351 } 352 else 353 { 354 boolean var8 = par1World.isBlockIndirectlyGettingPowered(par2, par3, par4) || par1World.isBlockIndirectlyGettingPowered(par2, par3 + 1, par4); 355 356 if ((var8 || par5 > 0 && Block.blocksList[par5].canProvidePower() || par5 == 0) && par5 != this.blockID) 357 { 358 this.onPoweredBlockChange(par1World, par2, par3, par4, var8); 359 } 360 } 361 } 362 else 363 { 364 if (par1World.getBlockId(par2, par3 - 1, par4) != this.blockID) 365 { 366 par1World.setBlockWithNotify(par2, par3, par4, 0); 367 } 368 369 if (par5 > 0 && par5 != this.blockID) 370 { 371 this.onNeighborBlockChange(par1World, par2, par3 - 1, par4, par5); 372 } 373 } 374 } 375 376 /** 377 * Returns the ID of the items to drop on destruction. 378 */ 379 public int idDropped(int par1, Random par2Random, int par3) 380 { 381 return (par1 & 8) != 0 ? 0 : (this.blockMaterial == Material.iron ? Item.doorSteel.shiftedIndex : Item.doorWood.shiftedIndex); 382 } 383 384 /** 385 * Ray traces through the blocks collision from start vector to end vector returning a ray trace hit. Args: world, 386 * x, y, z, startVec, endVec 387 */ 388 public MovingObjectPosition collisionRayTrace(World par1World, int par2, int par3, int par4, Vec3 par5Vec3, Vec3 par6Vec3) 389 { 390 this.setBlockBoundsBasedOnState(par1World, par2, par3, par4); 391 return super.collisionRayTrace(par1World, par2, par3, par4, par5Vec3, par6Vec3); 392 } 393 394 /** 395 * Checks to see if its valid to put this block at the specified coordinates. Args: world, x, y, z 396 */ 397 public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4) 398 { 399 return par3 >= 255 ? false : par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4) && super.canPlaceBlockAt(par1World, par2, par3, par4) && super.canPlaceBlockAt(par1World, par2, par3 + 1, par4); 400 } 401 402 /** 403 * Returns the mobility information of the block, 0 = free, 1 = can't push but can move over, 2 = total immobility 404 * and stop pistons 405 */ 406 public int getMobilityFlag() 407 { 408 return 1; 409 } 410 411 /** 412 * Returns the full metadata value created by combining the metadata of both blocks the door takes up. 413 */ 414 public int getFullMetadata(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) 415 { 416 int var5 = par1IBlockAccess.getBlockMetadata(par2, par3, par4); 417 boolean var6 = (var5 & 8) != 0; 418 int var7; 419 int var8; 420 421 if (var6) 422 { 423 var7 = par1IBlockAccess.getBlockMetadata(par2, par3 - 1, par4); 424 var8 = var5; 425 } 426 else 427 { 428 var7 = var5; 429 var8 = par1IBlockAccess.getBlockMetadata(par2, par3 + 1, par4); 430 } 431 432 boolean var9 = (var8 & 1) != 0; 433 return var7 & 7 | (var6 ? 8 : 0) | (var9 ? 16 : 0); 434 } 435 436 @SideOnly(Side.CLIENT) 437 438 /** 439 * only called by clickMiddleMouseButton , and passed to inventory.setCurrentItem (along with isCreative) 440 */ 441 public int idPicked(World par1World, int par2, int par3, int par4) 442 { 443 return this.blockMaterial == Material.iron ? Item.doorSteel.shiftedIndex : Item.doorWood.shiftedIndex; 444 } 445 }