001 package net.minecraft.block; 002 003 import cpw.mods.fml.relauncher.Side; 004 import cpw.mods.fml.relauncher.SideOnly; 005 import net.minecraft.block.material.Material; 006 import net.minecraft.creativetab.CreativeTabs; 007 import net.minecraft.entity.player.EntityPlayer; 008 import net.minecraft.util.AxisAlignedBB; 009 import net.minecraft.util.MovingObjectPosition; 010 import net.minecraft.util.Vec3; 011 import net.minecraft.world.IBlockAccess; 012 import net.minecraft.world.World; 013 014 import net.minecraftforge.common.ForgeDirection; 015 016 public class BlockTrapDoor extends Block 017 { 018 /** Set this to allow trapdoors to remain free-floating */ 019 public static boolean disableValidation = false; 020 021 protected BlockTrapDoor(int par1, Material par2Material) 022 { 023 super(par1, par2Material); 024 this.blockIndexInTexture = 84; 025 026 if (par2Material == Material.iron) 027 { 028 ++this.blockIndexInTexture; 029 } 030 031 float var3 = 0.5F; 032 float var4 = 1.0F; 033 this.setBlockBounds(0.5F - var3, 0.0F, 0.5F - var3, 0.5F + var3, var4, 0.5F + var3); 034 this.setCreativeTab(CreativeTabs.tabRedstone); 035 } 036 037 /** 038 * Is this block (a) opaque and (b) a full 1m cube? This determines whether or not to render the shared face of two 039 * adjacent blocks and also whether the player can attach torches, redstone wire, etc to this block. 040 */ 041 public boolean isOpaqueCube() 042 { 043 return false; 044 } 045 046 /** 047 * If this block doesn't render as an ordinary block it will return False (examples: signs, buttons, stairs, etc) 048 */ 049 public boolean renderAsNormalBlock() 050 { 051 return false; 052 } 053 054 public boolean getBlocksMovement(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) 055 { 056 return !isTrapdoorOpen(par1IBlockAccess.getBlockMetadata(par2, par3, par4)); 057 } 058 059 /** 060 * The type of render function that is called for this block 061 */ 062 public int getRenderType() 063 { 064 return 0; 065 } 066 067 @SideOnly(Side.CLIENT) 068 069 /** 070 * Returns the bounding box of the wired rectangular prism to render. 071 */ 072 public AxisAlignedBB getSelectedBoundingBoxFromPool(World par1World, int par2, int par3, int par4) 073 { 074 this.setBlockBoundsBasedOnState(par1World, par2, par3, par4); 075 return super.getSelectedBoundingBoxFromPool(par1World, par2, par3, par4); 076 } 077 078 /** 079 * Returns a bounding box from the pool of bounding boxes (this means this box can change after the pool has been 080 * cleared to be reused) 081 */ 082 public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4) 083 { 084 this.setBlockBoundsBasedOnState(par1World, par2, par3, par4); 085 return super.getCollisionBoundingBoxFromPool(par1World, par2, par3, par4); 086 } 087 088 /** 089 * Updates the blocks bounds based on its current state. Args: world, x, y, z 090 */ 091 public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) 092 { 093 this.setBlockBoundsForBlockRender(par1IBlockAccess.getBlockMetadata(par2, par3, par4)); 094 } 095 096 /** 097 * Sets the block's bounds for rendering it as an item 098 */ 099 public void setBlockBoundsForItemRender() 100 { 101 float var1 = 0.1875F; 102 this.setBlockBounds(0.0F, 0.5F - var1 / 2.0F, 0.0F, 1.0F, 0.5F + var1 / 2.0F, 1.0F); 103 } 104 105 public void setBlockBoundsForBlockRender(int par1) 106 { 107 float var2 = 0.1875F; 108 109 if ((par1 & 8) != 0) 110 { 111 this.setBlockBounds(0.0F, 1.0F - var2, 0.0F, 1.0F, 1.0F, 1.0F); 112 } 113 else 114 { 115 this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, var2, 1.0F); 116 } 117 118 if (isTrapdoorOpen(par1)) 119 { 120 if ((par1 & 3) == 0) 121 { 122 this.setBlockBounds(0.0F, 0.0F, 1.0F - var2, 1.0F, 1.0F, 1.0F); 123 } 124 125 if ((par1 & 3) == 1) 126 { 127 this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, var2); 128 } 129 130 if ((par1 & 3) == 2) 131 { 132 this.setBlockBounds(1.0F - var2, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F); 133 } 134 135 if ((par1 & 3) == 3) 136 { 137 this.setBlockBounds(0.0F, 0.0F, 0.0F, var2, 1.0F, 1.0F); 138 } 139 } 140 } 141 142 /** 143 * Called when the block is clicked by a player. Args: x, y, z, entityPlayer 144 */ 145 public void onBlockClicked(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer) {} 146 147 /** 148 * Called upon block activation (right click on the block.) 149 */ 150 public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9) 151 { 152 if (this.blockMaterial == Material.iron) 153 { 154 return true; 155 } 156 else 157 { 158 int var10 = par1World.getBlockMetadata(par2, par3, par4); 159 par1World.setBlockMetadataWithNotify(par2, par3, par4, var10 ^ 4); 160 par1World.playAuxSFXAtEntity(par5EntityPlayer, 1003, par2, par3, par4, 0); 161 return true; 162 } 163 } 164 165 public void onPoweredBlockChange(World par1World, int par2, int par3, int par4, boolean par5) 166 { 167 int var6 = par1World.getBlockMetadata(par2, par3, par4); 168 boolean var7 = (var6 & 4) > 0; 169 170 if (var7 != par5) 171 { 172 par1World.setBlockMetadataWithNotify(par2, par3, par4, var6 ^ 4); 173 par1World.playAuxSFXAtEntity((EntityPlayer)null, 1003, par2, par3, par4, 0); 174 } 175 } 176 177 /** 178 * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are 179 * their own) Args: x, y, z, neighbor blockID 180 */ 181 public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) 182 { 183 if (!par1World.isRemote) 184 { 185 int var6 = par1World.getBlockMetadata(par2, par3, par4); 186 int var7 = par2; 187 int var8 = par4; 188 189 if ((var6 & 3) == 0) 190 { 191 var8 = par4 + 1; 192 } 193 194 if ((var6 & 3) == 1) 195 { 196 --var8; 197 } 198 199 if ((var6 & 3) == 2) 200 { 201 var7 = par2 + 1; 202 } 203 204 if ((var6 & 3) == 3) 205 { 206 --var7; 207 } 208 209 if (!(isValidSupportBlock(par1World.getBlockId(var7, par3, var8)) || par1World.isBlockSolidOnSide(var7, par3, var8, ForgeDirection.getOrientation((var6 & 3) + 2)))) 210 { 211 par1World.setBlockWithNotify(par2, par3, par4, 0); 212 this.dropBlockAsItem(par1World, par2, par3, par4, var6, 0); 213 } 214 215 boolean var9 = par1World.isBlockIndirectlyGettingPowered(par2, par3, par4); 216 217 if (var9 || par5 > 0 && Block.blocksList[par5].canProvidePower()) 218 { 219 this.onPoweredBlockChange(par1World, par2, par3, par4, var9); 220 } 221 } 222 } 223 224 /** 225 * Ray traces through the blocks collision from start vector to end vector returning a ray trace hit. Args: world, 226 * x, y, z, startVec, endVec 227 */ 228 public MovingObjectPosition collisionRayTrace(World par1World, int par2, int par3, int par4, Vec3 par5Vec3, Vec3 par6Vec3) 229 { 230 this.setBlockBoundsBasedOnState(par1World, par2, par3, par4); 231 return super.collisionRayTrace(par1World, par2, par3, par4, par5Vec3, par6Vec3); 232 } 233 234 /** 235 * Called when a block is placed using its ItemBlock. Args: World, X, Y, Z, side, hitX, hitY, hitZ, block metadata 236 */ 237 public int onBlockPlaced(World par1World, int par2, int par3, int par4, int par5, float par6, float par7, float par8, int par9) 238 { 239 int var10 = 0; 240 241 if (par5 == 2) 242 { 243 var10 = 0; 244 } 245 246 if (par5 == 3) 247 { 248 var10 = 1; 249 } 250 251 if (par5 == 4) 252 { 253 var10 = 2; 254 } 255 256 if (par5 == 5) 257 { 258 var10 = 3; 259 } 260 261 if (par5 != 1 && par5 != 0 && par7 > 0.5F) 262 { 263 var10 |= 8; 264 } 265 266 return var10; 267 } 268 269 /** 270 * checks to see if you can place this block can be placed on that side of a block: BlockLever overrides 271 */ 272 public boolean canPlaceBlockOnSide(World par1World, int par2, int par3, int par4, int par5) 273 { 274 if (disableValidation) 275 { 276 return true; 277 } 278 if (par5 == 0) 279 { 280 return false; 281 } 282 else if (par5 == 1) 283 { 284 return false; 285 } 286 else 287 { 288 if (par5 == 2) 289 { 290 ++par4; 291 } 292 293 if (par5 == 3) 294 { 295 --par4; 296 } 297 298 if (par5 == 4) 299 { 300 ++par2; 301 } 302 303 if (par5 == 5) 304 { 305 --par2; 306 } 307 308 return isValidSupportBlock(par1World.getBlockId(par2, par3, par4)) || par1World.isBlockSolidOnSide(par2, par3, par4, ForgeDirection.UP); 309 } 310 } 311 312 public static boolean isTrapdoorOpen(int par0) 313 { 314 return (par0 & 4) != 0; 315 } 316 317 /** 318 * Checks if the block ID is a valid support block for the trap door to connect with. If it is not the trapdoor is 319 * dropped into the world. 320 */ 321 private static boolean isValidSupportBlock(int par0) 322 { 323 if (disableValidation) 324 { 325 return true; 326 } 327 if (par0 <= 0) 328 { 329 return false; 330 } 331 else 332 { 333 Block var1 = Block.blocksList[par0]; 334 return var1 != null && var1.blockMaterial.isOpaque() && var1.renderAsNormalBlock() || var1 == Block.glowStone || var1 instanceof BlockHalfSlab || var1 instanceof BlockStairs; 335 } 336 } 337 }