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            this.onBlockActivated(par1World, par2, par3, par4, par5EntityPlayer, 0, 0.0F, 0.0F, 0.0F);
258        }
259    
260        /**
261         * Called upon block activation (right click on the block.)
262         */
263        public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9)
264        {
265            if (this.blockMaterial == Material.iron)
266            {
267                return false; //Allow items to interact with the door
268            }
269            else
270            {
271                int var10 = this.getFullMetadata(par1World, par2, par3, par4);
272                int var11 = var10 & 7;
273                var11 ^= 4;
274    
275                if ((var10 & 8) == 0)
276                {
277                    par1World.setBlockMetadataWithNotify(par2, par3, par4, var11);
278                    par1World.markBlocksDirty(par2, par3, par4, par2, par3, par4);
279                }
280                else
281                {
282                    par1World.setBlockMetadataWithNotify(par2, par3 - 1, par4, var11);
283                    par1World.markBlocksDirty(par2, par3 - 1, par4, par2, par3, par4);
284                }
285    
286                par1World.playAuxSFXAtEntity(par5EntityPlayer, 1003, par2, par3, par4, 0);
287                return true;
288            }
289        }
290    
291        /**
292         * A function to open a door.
293         */
294        public void onPoweredBlockChange(World par1World, int par2, int par3, int par4, boolean par5)
295        {
296            int var6 = this.getFullMetadata(par1World, par2, par3, par4);
297            boolean var7 = (var6 & 4) != 0;
298    
299            if (var7 != par5)
300            {
301                int var8 = var6 & 7;
302                var8 ^= 4;
303    
304                if ((var6 & 8) == 0)
305                {
306                    par1World.setBlockMetadataWithNotify(par2, par3, par4, var8);
307                    par1World.markBlocksDirty(par2, par3, par4, par2, par3, par4);
308                }
309                else
310                {
311                    par1World.setBlockMetadataWithNotify(par2, par3 - 1, par4, var8);
312                    par1World.markBlocksDirty(par2, par3 - 1, par4, par2, par3, par4);
313                }
314    
315                par1World.playAuxSFXAtEntity((EntityPlayer)null, 1003, par2, par3, par4, 0);
316            }
317        }
318    
319        /**
320         * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are
321         * their own) Args: x, y, z, neighbor blockID
322         */
323        public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5)
324        {
325            int var6 = par1World.getBlockMetadata(par2, par3, par4);
326    
327            if ((var6 & 8) == 0)
328            {
329                boolean var7 = false;
330    
331                if (par1World.getBlockId(par2, par3 + 1, par4) != this.blockID)
332                {
333                    par1World.setBlockWithNotify(par2, par3, par4, 0);
334                    var7 = true;
335                }
336    
337                if (!par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4))
338                {
339                    par1World.setBlockWithNotify(par2, par3, par4, 0);
340                    var7 = true;
341    
342                    if (par1World.getBlockId(par2, par3 + 1, par4) == this.blockID)
343                    {
344                        par1World.setBlockWithNotify(par2, par3 + 1, par4, 0);
345                    }
346                }
347    
348                if (var7)
349                {
350                    if (!par1World.isRemote)
351                    {
352                        this.dropBlockAsItem(par1World, par2, par3, par4, var6, 0);
353                    }
354                }
355                else
356                {
357                    boolean var8 = par1World.isBlockIndirectlyGettingPowered(par2, par3, par4) || par1World.isBlockIndirectlyGettingPowered(par2, par3 + 1, par4);
358    
359                    if ((var8 || par5 > 0 && Block.blocksList[par5].canProvidePower() || par5 == 0) && par5 != this.blockID)
360                    {
361                        this.onPoweredBlockChange(par1World, par2, par3, par4, var8);
362                    }
363                }
364            }
365            else
366            {
367                if (par1World.getBlockId(par2, par3 - 1, par4) != this.blockID)
368                {
369                    par1World.setBlockWithNotify(par2, par3, par4, 0);
370                }
371    
372                if (par5 > 0 && par5 != this.blockID)
373                {
374                    this.onNeighborBlockChange(par1World, par2, par3 - 1, par4, par5);
375                }
376            }
377        }
378    
379        /**
380         * Returns the ID of the items to drop on destruction.
381         */
382        public int idDropped(int par1, Random par2Random, int par3)
383        {
384            return (par1 & 8) != 0 ? 0 : (this.blockMaterial == Material.iron ? Item.doorSteel.shiftedIndex : Item.doorWood.shiftedIndex);
385        }
386    
387        /**
388         * Ray traces through the blocks collision from start vector to end vector returning a ray trace hit. Args: world,
389         * x, y, z, startVec, endVec
390         */
391        public MovingObjectPosition collisionRayTrace(World par1World, int par2, int par3, int par4, Vec3 par5Vec3, Vec3 par6Vec3)
392        {
393            this.setBlockBoundsBasedOnState(par1World, par2, par3, par4);
394            return super.collisionRayTrace(par1World, par2, par3, par4, par5Vec3, par6Vec3);
395        }
396    
397        /**
398         * Checks to see if its valid to put this block at the specified coordinates. Args: world, x, y, z
399         */
400        public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4)
401        {
402            return par3 >= 255 ? false : par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4) && super.canPlaceBlockAt(par1World, par2, par3, par4) && super.canPlaceBlockAt(par1World, par2, par3 + 1, par4);
403        }
404    
405        /**
406         * Returns the mobility information of the block, 0 = free, 1 = can't push but can move over, 2 = total immobility
407         * and stop pistons
408         */
409        public int getMobilityFlag()
410        {
411            return 1;
412        }
413    
414        /**
415         * Returns the full metadata value created by combining the metadata of both blocks the door takes up.
416         */
417        public int getFullMetadata(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
418        {
419            int var5 = par1IBlockAccess.getBlockMetadata(par2, par3, par4);
420            boolean var6 = (var5 & 8) != 0;
421            int var7;
422            int var8;
423    
424            if (var6)
425            {
426                var7 = par1IBlockAccess.getBlockMetadata(par2, par3 - 1, par4);
427                var8 = var5;
428            }
429            else
430            {
431                var7 = var5;
432                var8 = par1IBlockAccess.getBlockMetadata(par2, par3 + 1, par4);
433            }
434    
435            boolean var9 = (var8 & 1) != 0;
436            return var7 & 7 | (var6 ? 8 : 0) | (var9 ? 16 : 0);
437        }
438    
439        @SideOnly(Side.CLIENT)
440    
441        /**
442         * only called by clickMiddleMouseButton , and passed to inventory.setCurrentItem (along with isCreative)
443         */
444        public int idPicked(World par1World, int par2, int par3, int par4)
445        {
446            return this.blockMaterial == Material.iron ? Item.doorSteel.shiftedIndex : Item.doorWood.shiftedIndex;
447        }
448    }