    001    package net.minecraft.block;
    002
    003    import cpw.mods.fml.relauncher.Side;
    004    import cpw.mods.fml.relauncher.SideOnly;
    005    import java.util.Random;
    006    import net.minecraft.block.material.Material;
    007    import net.minecraft.entity.player.EntityPlayer;
    008    import net.minecraft.item.Item;
    009    import net.minecraft.util.AxisAlignedBB;
    010    import net.minecraft.util.MovingObjectPosition;
    011    import net.minecraft.util.Vec3;
    012    import net.minecraft.world.IBlockAccess;
    013    import net.minecraft.world.World;
    014
    015    public class BlockDoor extends Block
    016    {
    017        protected BlockDoor(int par1, Material par2Material)
    018        {
    019            super(par1, par2Material);
    020            this.blockIndexInTexture = 97;
    021
    022            if (par2Material == Material.iron)
    023            {
    024                ++this.blockIndexInTexture;
    025            }
    026
    027            float var3 = 0.5F;
    028            float var4 = 1.0F;
    029            this.setBlockBounds(0.5F - var3, 0.0F, 0.5F - var3, 0.5F + var3, var4, 0.5F + var3);
    030        }
    031
    032        @SideOnly(Side.CLIENT)
    033
    034        /**
    035         * Retrieves the block texture to use based on the display side. Args: iBlockAccess, x, y, z, side
    036         */
    037        public int getBlockTexture(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5)
    038        {
    039            if (par5 != 0 && par5 != 1)
    040            {
    041                int var6 = this.getFullMetadata(par1IBlockAccess, par2, par3, par4);
    042                int var7 = this.blockIndexInTexture;
    043
    044                if ((var6 & 8) != 0)
    045                {
    046                    var7 -= 16;
    047                }
    048
    049                int var8 = var6 & 3;
    050                boolean var9 = (var6 & 4) != 0;
    051
    052                if (var9)
    053                {
    054                    if (var8 == 0 && par5 == 2)
    055                    {
    056                        var7 = -var7;
    057                    }
    058                    else if (var8 == 1 && par5 == 5)
    059                    {
    060                        var7 = -var7;
    061                    }
    062                    else if (var8 == 2 && par5 == 3)
    063                    {
    064                        var7 = -var7;
    065                    }
    066                    else if (var8 == 3 && par5 == 4)
    067                    {
    068                        var7 = -var7;
    069                    }
    070                }
    071                else
    072                {
    073                    if (var8 == 0 && par5 == 5)
    074                    {
    075                        var7 = -var7;
    076                    }
    077                    else if (var8 == 1 && par5 == 3)
    078                    {
    079                        var7 = -var7;
    080                    }
    081                    else if (var8 == 2 && par5 == 4)
    082                    {
    083                        var7 = -var7;
    084                    }
    085                    else if (var8 == 3 && par5 == 2)
    086                    {
    087                        var7 = -var7;
    088                    }
    089
    090                    if ((var6 & 16) != 0)
    091                    {
    092                        var7 = -var7;
    093                    }
    094                }
    095
    096                return var7;
    097            }
    098            else
    099            {
    100                return this.blockIndexInTexture;
    101            }
    102        }
    103
    104        /**
    105         * Is this block (a) opaque and (b) a full 1m cube?  This determines whether or not to render the shared face of two
    106         * adjacent blocks and also whether the player can attach torches, redstone wire, etc to this block.
    107         */
    108        public boolean isOpaqueCube()
    109        {
    110            return false;
    111        }
    112
    113        public boolean getBlocksMovement(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
    114        {
    115            int var5 = this.getFullMetadata(par1IBlockAccess, par2, par3, par4);
    116            return (var5 & 4) != 0;
    117        }
    118
    119        /**
    120         * If this block doesn't render as an ordinary block it will return False (examples: signs, buttons, stairs, etc)
    121         */
    122        public boolean renderAsNormalBlock()
    123        {
    124            return false;
    125        }
    126
    127        /**
    128         * The type of render function that is called for this block
    129         */
    130        public int getRenderType()
    131        {
    132            return 7;
    133        }
    134
    135        @SideOnly(Side.CLIENT)
    136
    137        /**
    138         * Returns the bounding box of the wired rectangular prism to render.
    139         */
    140        public AxisAlignedBB getSelectedBoundingBoxFromPool(World par1World, int par2, int par3, int par4)
    141        {
    142            this.setBlockBoundsBasedOnState(par1World, par2, par3, par4);
    143            return super.getSelectedBoundingBoxFromPool(par1World, par2, par3, par4);
    144        }
    145
    146        /**
    147         * Returns a bounding box from the pool of bounding boxes (this means this box can change after the pool has been
    148         * cleared to be reused)
    149         */
    150        public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4)
    151        {
    152            this.setBlockBoundsBasedOnState(par1World, par2, par3, par4);
    153            return super.getCollisionBoundingBoxFromPool(par1World, par2, par3, par4);
    154        }
    155
    156        /**
    157         * Updates the blocks bounds based on its current state. Args: world, x, y, z
    158         */
    159        public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
    160        {
    161            this.setDoorRotation(this.getFullMetadata(par1IBlockAccess, par2, par3, par4));
    162        }
    163
    164        /**
    165         * Returns 0, 1, 2 or 3 depending on where the hinge is.
    166         */
    167        public int getDoorOrientation(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
    168        {
    169            return this.getFullMetadata(par1IBlockAccess, par2, par3, par4) & 3;
    170        }
    171
    172        public boolean isDoorOpen(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
    173        {
    174            return (this.getFullMetadata(par1IBlockAccess, par2, par3, par4) & 4) != 0;
    175        }
    176
    177        private void setDoorRotation(int par1)
    178        {
    179            float var2 = 0.1875F;
    180            this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 2.0F, 1.0F);
    181            int var3 = par1 & 3;
    182            boolean var4 = (par1 & 4) != 0;
    183            boolean var5 = (par1 & 16) != 0;
    184
    185            if (var3 == 0)
    186            {
    187                if (var4)
    188                {
    189                    if (!var5)
    190                    {
    191                        this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, var2);
    192                    }
    193                    else
    194                    {
    195                        this.setBlockBounds(0.0F, 0.0F, 1.0F - var2, 1.0F, 1.0F, 1.0F);
    196                    }
    197                }
    198                else
    199                {
    200                    this.setBlockBounds(0.0F, 0.0F, 0.0F, var2, 1.0F, 1.0F);
    201                }
    202            }
    203            else if (var3 == 1)
    204            {
    205                if (var4)
    206                {
    207                    if (!var5)
    208                    {
    209                        this.setBlockBounds(1.0F - var2, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
    210                    }
    211                    else
    212                    {
    213                        this.setBlockBounds(0.0F, 0.0F, 0.0F, var2, 1.0F, 1.0F);
    214                    }
    215                }
    216                else
    217                {
    218                    this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, var2);
    219                }
    220            }
    221            else if (var3 == 2)
    222            {
    223                if (var4)
    224                {
    225                    if (!var5)
    226                    {
    227                        this.setBlockBounds(0.0F, 0.0F, 1.0F - var2, 1.0F, 1.0F, 1.0F);
    228                    }
    229                    else
    230                    {
    231                        this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 1.0F, var2);
    232                    }
    233                }
    234                else
    235                {
    236                    this.setBlockBounds(1.0F - var2, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
    237                }
    238            }
    239            else if (var3 == 3)
    240            {
    241                if (var4)
    242                {
    243                    if (!var5)
    244                    {
    245                        this.setBlockBounds(0.0F, 0.0F, 0.0F, var2, 1.0F, 1.0F);
    246                    }
    247                    else
    248                    {
    249                        this.setBlockBounds(1.0F - var2, 0.0F, 0.0F, 1.0F, 1.0F, 1.0F);
    250                    }
    251                }
    252                else
    253                {
    254                    this.setBlockBounds(0.0F, 0.0F, 1.0F - var2, 1.0F, 1.0F, 1.0F);
    255                }
    256            }
    257        }
    258
    259        /**
    260         * Called when the block is clicked by a player. Args: x, y, z, entityPlayer
    261         */
    262        public void onBlockClicked(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer) {}
    263
    264        /**
    265         * Called upon block activation (right click on the block.)
    266         */
    267        public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9)
    268        {
    269            if (this.blockMaterial == Material.iron)
    270            {
    271                return false; //Allow items to interact with the door
    272            }
    273            else
    274            {
    275                int var10 = this.getFullMetadata(par1World, par2, par3, par4);
    276                int var11 = var10 & 7;
    277                var11 ^= 4;
    278
    279                if ((var10 & 8) == 0)
    280                {
    281                    par1World.setBlockMetadataWithNotify(par2, par3, par4, var11);
    282                    par1World.markBlockRangeForRenderUpdate(par2, par3, par4, par2, par3, par4);
    283                }
    284                else
    285                {
    286                    par1World.setBlockMetadataWithNotify(par2, par3 - 1, par4, var11);
    287                    par1World.markBlockRangeForRenderUpdate(par2, par3 - 1, par4, par2, par3, par4);
    288                }
    289
    290                par1World.playAuxSFXAtEntity(par5EntityPlayer, 1003, par2, par3, par4, 0);
    291                return true;
    292            }
    293        }
    294
    295        /**
    296         * A function to open a door.
    297         */
    298        public void onPoweredBlockChange(World par1World, int par2, int par3, int par4, boolean par5)
    299        {
    300            int var6 = this.getFullMetadata(par1World, par2, par3, par4);
    301            boolean var7 = (var6 & 4) != 0;
    302
    303            if (var7 != par5)
    304            {
    305                int var8 = var6 & 7;
    306                var8 ^= 4;
    307
    308                if ((var6 & 8) == 0)
    309                {
    310                    par1World.setBlockMetadataWithNotify(par2, par3, par4, var8);
    311                    par1World.markBlockRangeForRenderUpdate(par2, par3, par4, par2, par3, par4);
    312                }
    313                else
    314                {
    315                    par1World.setBlockMetadataWithNotify(par2, par3 - 1, par4, var8);
    316                    par1World.markBlockRangeForRenderUpdate(par2, par3 - 1, par4, par2, par3, par4);
    317                }
    318
    319                par1World.playAuxSFXAtEntity((EntityPlayer)null, 1003, par2, par3, par4, 0);
    320            }
    321        }
    322
    323        /**
    324         * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are
    325         * their own) Args: x, y, z, neighbor blockID
    326         */
    327        public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5)
    328        {
    329            int var6 = par1World.getBlockMetadata(par2, par3, par4);
    330
    331            if ((var6 & 8) == 0)
    332            {
    333                boolean var7 = false;
    334
    335                if (par1World.getBlockId(par2, par3 + 1, par4) != this.blockID)
    336                {
    337                    par1World.setBlockWithNotify(par2, par3, par4, 0);
    338                    var7 = true;
    339                }
    340
    341                if (!par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4))
    342                {
    343                    par1World.setBlockWithNotify(par2, par3, par4, 0);
    344                    var7 = true;
    345
    346                    if (par1World.getBlockId(par2, par3 + 1, par4) == this.blockID)
    347                    {
    348                        par1World.setBlockWithNotify(par2, par3 + 1, par4, 0);
    349                    }
    350                }
    351
    352                if (var7)
    353                {
    354                    if (!par1World.isRemote)
    355                    {
    356                        this.dropBlockAsItem(par1World, par2, par3, par4, var6, 0);
    357                    }
    358                }
    359                else
    360                {
    361                    boolean var8 = par1World.isBlockIndirectlyGettingPowered(par2, par3, par4) || par1World.isBlockIndirectlyGettingPowered(par2, par3 + 1, par4);
    362
    363                    if ((var8 || par5 > 0 && Block.blocksList[par5].canProvidePower()) && par5 != this.blockID)
    364                    {
    365                        this.onPoweredBlockChange(par1World, par2, par3, par4, var8);
    366                    }
    367                }
    368            }
    369            else
    370            {
    371                if (par1World.getBlockId(par2, par3 - 1, par4) != this.blockID)
    372                {
    373                    par1World.setBlockWithNotify(par2, par3, par4, 0);
    374                }
    375
    376                if (par5 > 0 && par5 != this.blockID)
    377                {
    378                    this.onNeighborBlockChange(par1World, par2, par3 - 1, par4, par5);
    379                }
    380            }
    381        }
    382
    383        /**
    384         * Returns the ID of the items to drop on destruction.
    385         */
    386        public int idDropped(int par1, Random par2Random, int par3)
    387        {
    388            return (par1 & 8) != 0 ? 0 : (this.blockMaterial == Material.iron ? Item.doorSteel.shiftedIndex : Item.doorWood.shiftedIndex);
    389        }
    390
    391        /**
    392         * Ray traces through the blocks collision from start vector to end vector returning a ray trace hit. Args: world,
    393         * x, y, z, startVec, endVec
    394         */
    395        public MovingObjectPosition collisionRayTrace(World par1World, int par2, int par3, int par4, Vec3 par5Vec3, Vec3 par6Vec3)
    396        {
    397            this.setBlockBoundsBasedOnState(par1World, par2, par3, par4);
    398            return super.collisionRayTrace(par1World, par2, par3, par4, par5Vec3, par6Vec3);
    399        }
    400
    401        /**
    402         * Checks to see if its valid to put this block at the specified coordinates. Args: world, x, y, z
    403         */
    404        public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4)
    405        {
    406            return par3 >= 255 ? false : par1World.doesBlockHaveSolidTopSurface(par2, par3 - 1, par4) && super.canPlaceBlockAt(par1World, par2, par3, par4) && super.canPlaceBlockAt(par1World, par2, par3 + 1, par4);
    407        }
    408
    409        /**
    410         * Returns the mobility information of the block, 0 = free, 1 = can't push but can move over, 2 = total immobility
    411         * and stop pistons
    412         */
    413        public int getMobilityFlag()
    414        {
    415            return 1;
    416        }
    417
    418        /**
    419         * Returns the full metadata value created by combining the metadata of both blocks the door takes up.
    420         */
    421        public int getFullMetadata(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
    422        {
    423            int var5 = par1IBlockAccess.getBlockMetadata(par2, par3, par4);
    424            boolean var6 = (var5 & 8) != 0;
    425            int var7;
    426            int var8;
    427
    428            if (var6)
    429            {
    430                var7 = par1IBlockAccess.getBlockMetadata(par2, par3 - 1, par4);
    431                var8 = var5;
    432            }
    433            else
    434            {
    435                var7 = var5;
    436                var8 = par1IBlockAccess.getBlockMetadata(par2, par3 + 1, par4);
    437            }
    438
    439            boolean var9 = (var8 & 1) != 0;
    440            return var7 & 7 | (var6 ? 8 : 0) | (var9 ? 16 : 0);
    441        }
    442
    443        @SideOnly(Side.CLIENT)
    444
    445        /**
    446         * only called by clickMiddleMouseButton , and passed to inventory.setCurrentItem (along with isCreative)
    447         */
    448        public int idPicked(World par1World, int par2, int par3, int par4)
    449        {
    450            return this.blockMaterial == Material.iron ? Item.doorSteel.shiftedIndex : Item.doorWood.shiftedIndex;
    451        }
    452
    453        /**
    454         * Called when the block is attempted to be harvested
    455         */
    456        public void onBlockHarvested(World par1World, int par2, int par3, int par4, int par5, EntityPlayer par6EntityPlayer)
    457        {
    458            if (par6EntityPlayer.capabilities.isCreativeMode && (par5 & 8) != 0 && par1World.getBlockId(par2, par3 - 1, par4) == this.blockID)
    459            {
    460                par1World.setBlockWithNotify(par2, par3 - 1, par4, 0);
    461            }
    462        }
    463    }