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