    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.markBlocksDirty(par2, par3, par4, par2, par3, par4);
    276                }
    277                else
    278                {
    279                    par1World.setBlockMetadataWithNotify(par2, par3 - 1, par4, var11);
    280                    par1World.markBlocksDirty(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.markBlocksDirty(par2, par3, par4, par2, par3, par4);
    305                }
    306                else
    307                {
    308                    par1World.setBlockMetadataWithNotify(par2, par3 - 1, par4, var8);
    309                    par1World.markBlocksDirty(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    }