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    
100            if ((par1 & 8) != 0)
101            {
102                this.setBlockBounds(0.0F, 1.0F - var2, 0.0F, 1.0F, 1.0F, 1.0F);
103            }
104            else
105            {
106                this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, var2, 1.0F);
107            }
108    
109            if (isTrapdoorOpen(par1))
110            {
111                if ((par1 & 3) == 0)
112                {
113                    this.setBlockBounds(0.0F, 0.0F, 1.0F - var2, 1.0F, 1.0F, 1.0F);
114                }
115    
116                if ((par1 & 3) == 1)
117                {
118                    this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, var2);
119                }
120    
121                if ((par1 & 3) == 2)
122                {
123                    this.setBlockBounds(1.0F - var2, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
124                }
125    
126                if ((par1 & 3) == 3)
127                {
128                    this.setBlockBounds(0.0F, 0.0F, 0.0F, var2, 1.0F, 1.0F);
129                }
130            }
131        }
132    
133        /**
134         * Called when the block is clicked by a player. Args: x, y, z, entityPlayer
135         */
136        public void onBlockClicked(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer) {}
137    
138        /**
139         * Called upon block activation (right click on the block.)
140         */
141        public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9)
142        {
143            if (this.blockMaterial == Material.iron)
144            {
145                return true;
146            }
147            else
148            {
149                int var10 = par1World.getBlockMetadata(par2, par3, par4);
150                par1World.setBlockMetadataWithNotify(par2, par3, par4, var10 ^ 4);
151                par1World.playAuxSFXAtEntity(par5EntityPlayer, 1003, par2, par3, par4, 0);
152                return true;
153            }
154        }
155    
156        public void onPoweredBlockChange(World par1World, int par2, int par3, int par4, boolean par5)
157        {
158            int var6 = par1World.getBlockMetadata(par2, par3, par4);
159            boolean var7 = (var6 & 4) > 0;
160    
161            if (var7 != par5)
162            {
163                par1World.setBlockMetadataWithNotify(par2, par3, par4, var6 ^ 4);
164                par1World.playAuxSFXAtEntity((EntityPlayer)null, 1003, par2, par3, par4, 0);
165            }
166        }
167    
168        /**
169         * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are
170         * their own) Args: x, y, z, neighbor blockID
171         */
172        public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5)
173        {
174            if (!par1World.isRemote)
175            {
176                int var6 = par1World.getBlockMetadata(par2, par3, par4);
177                int var7 = par2;
178                int var8 = par4;
179    
180                if ((var6 & 3) == 0)
181                {
182                    var8 = par4 + 1;
183                }
184    
185                if ((var6 & 3) == 1)
186                {
187                    --var8;
188                }
189    
190                if ((var6 & 3) == 2)
191                {
192                    var7 = par2 + 1;
193                }
194    
195                if ((var6 & 3) == 3)
196                {
197                    --var7;
198                }
199    
200                if (!(isValidSupportBlock(par1World.getBlockId(var7, par3, var8)) || par1World.isBlockSolidOnSide(var7, par3, var8, ForgeDirection.getOrientation((var6 & 3) + 2))))
201                {
202                    par1World.setBlockWithNotify(par2, par3, par4, 0);
203                    this.dropBlockAsItem(par1World, par2, par3, par4, var6, 0);
204                }
205    
206                boolean var9 = par1World.isBlockIndirectlyGettingPowered(par2, par3, par4);
207    
208                if (var9 || par5 > 0 && Block.blocksList[par5].canProvidePower() || par5 == 0)
209                {
210                    this.onPoweredBlockChange(par1World, par2, par3, par4, var9);
211                }
212            }
213        }
214    
215        /**
216         * Ray traces through the blocks collision from start vector to end vector returning a ray trace hit. Args: world,
217         * x, y, z, startVec, endVec
218         */
219        public MovingObjectPosition collisionRayTrace(World par1World, int par2, int par3, int par4, Vec3 par5Vec3, Vec3 par6Vec3)
220        {
221            this.setBlockBoundsBasedOnState(par1World, par2, par3, par4);
222            return super.collisionRayTrace(par1World, par2, par3, par4, par5Vec3, par6Vec3);
223        }
224    
225        /**
226         * called before onBlockPlacedBy by ItemBlock and ItemReed
227         */
228        public void updateBlockMetadata(World par1World, int par2, int par3, int par4, int par5, float par6, float par7, float par8)
229        {
230            int var9 = 0;
231    
232            if (par5 == 2)
233            {
234                var9 = 0;
235            }
236    
237            if (par5 == 3)
238            {
239                var9 = 1;
240            }
241    
242            if (par5 == 4)
243            {
244                var9 = 2;
245            }
246    
247            if (par5 == 5)
248            {
249                var9 = 3;
250            }
251    
252            int var10 = Block.trapdoor.blockID;
253    
254            if (par5 != 1 && par5 != 0 && par7 > 0.5F)
255            {
256                var9 |= 8;
257            }
258    
259            par1World.setBlockAndMetadataWithNotify(par2, par3, par4, var10, var9);
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 var1 = Block.blocksList[par0];
327                return var1 != null && var1.blockMaterial.isOpaque() && var1.renderAsNormalBlock() || var1 == Block.glowStone;
328            }
329        }
330    }