    001package net.minecraft.block;
    002
    003import cpw.mods.fml.relauncher.Side;
    004import cpw.mods.fml.relauncher.SideOnly;
    005import java.util.Random;
    006import net.minecraft.block.material.Material;
    007import net.minecraft.entity.player.EntityPlayer;
    008import net.minecraft.item.Item;
    009import net.minecraft.util.AxisAlignedBB;
    010import net.minecraft.util.MovingObjectPosition;
    011import net.minecraft.util.Vec3;
    012import net.minecraft.world.IBlockAccess;
    013import net.minecraft.world.World;
    014
    015public 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.itemID : Item.doorWood.itemID);
    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.itemID : Item.doorWood.itemID;
    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}