    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    }