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