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.markBlockRangeForRenderUpdate(par2, par3, par4, par2, par3, par4);
276                }
277                else
278                {
279                    par1World.setBlockMetadataWithNotify(par2, par3 - 1, par4, var11);
280                    par1World.markBlockRangeForRenderUpdate(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.markBlockRangeForRenderUpdate(par2, par3, par4, par2, par3, par4);
305                }
306                else
307                {
308                    par1World.setBlockMetadataWithNotify(par2, par3 - 1, par4, var8);
309                    par1World.markBlockRangeForRenderUpdate(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 != 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    
446        /**
447         * Called when the block is attempted to be harvested
448         */
449        public void onBlockHarvested(World par1World, int par2, int par3, int par4, int par5, EntityPlayer par6EntityPlayer)
450        {
451            if (par6EntityPlayer.capabilities.isCreativeMode && (par5 & 8) != 0 && par1World.getBlockId(par2, par3 - 1, par4) == this.blockID)
452            {
453                par1World.setBlockWithNotify(par2, par3 - 1, par4, 0);
454            }
455        }
456    }