    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.Iterator;
    006    import java.util.Random;
    007
    008    public class BlockBed extends BlockDirectional
    009    {
    010        /** Maps the foot-of-bed block to the head-of-bed block. */
    011        public static final int[][] footBlockToHeadBlockMap = new int[][] {{0, 1}, { -1, 0}, {0, -1}, {1, 0}};
    012
    013        public BlockBed(int par1)
    014        {
    015            super(par1, 134, Material.cloth);
    016            this.setBounds();
    017        }
    018
    019        /**
    020         * Called upon block activation (right click on the block.)
    021         */
    022        public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9)
    023        {
    024            if (par1World.isRemote)
    025            {
    026                return true;
    027            }
    028            else
    029            {
    030                int var10 = par1World.getBlockMetadata(par2, par3, par4);
    031
    032                if (!isBlockHeadOfBed(var10))
    033                {
    034                    int var11 = getDirection(var10);
    035                    par2 += footBlockToHeadBlockMap[var11][0];
    036                    par4 += footBlockToHeadBlockMap[var11][1];
    037
    038                    if (par1World.getBlockId(par2, par3, par4) != this.blockID)
    039                    {
    040                        return true;
    041                    }
    042
    043                    var10 = par1World.getBlockMetadata(par2, par3, par4);
    044                }
    045
    046                if (!par1World.provider.canRespawnHere())
    047                {
    048                    double var19 = (double)par2 + 0.5D;
    049                    double var21 = (double)par3 + 0.5D;
    050                    double var15 = (double)par4 + 0.5D;
    051                    par1World.setBlockWithNotify(par2, par3, par4, 0);
    052                    int var17 = getDirection(var10);
    053                    par2 += footBlockToHeadBlockMap[var17][0];
    054                    par4 += footBlockToHeadBlockMap[var17][1];
    055
    056                    if (par1World.getBlockId(par2, par3, par4) == this.blockID)
    057                    {
    058                        par1World.setBlockWithNotify(par2, par3, par4, 0);
    059                        var19 = (var19 + (double)par2 + 0.5D) / 2.0D;
    060                        var21 = (var21 + (double)par3 + 0.5D) / 2.0D;
    061                        var15 = (var15 + (double)par4 + 0.5D) / 2.0D;
    062                    }
    063
    064                    par1World.newExplosion((Entity)null, (double)((float)par2 + 0.5F), (double)((float)par3 + 0.5F), (double)((float)par4 + 0.5F), 5.0F, true, true);
    065                    return true;
    066                }
    067                else
    068                {
    069                    if (isBedOccupied(var10))
    070                    {
    071                        EntityPlayer var18 = null;
    072                        Iterator var12 = par1World.playerEntities.iterator();
    073
    074                        while (var12.hasNext())
    075                        {
    076                            EntityPlayer var13 = (EntityPlayer)var12.next();
    077
    078                            if (var13.isPlayerSleeping())
    079                            {
    080                                ChunkCoordinates var14 = var13.playerLocation;
    081
    082                                if (var14.posX == par2 && var14.posY == par3 && var14.posZ == par4)
    083                                {
    084                                    var18 = var13;
    085                                }
    086                            }
    087                        }
    088
    089                        if (var18 != null)
    090                        {
    091                            par5EntityPlayer.addChatMessage("tile.bed.occupied");
    092                            return true;
    093                        }
    094
    095                        setBedOccupied(par1World, par2, par3, par4, false);
    096                    }
    097
    098                    EnumStatus var20 = par5EntityPlayer.sleepInBedAt(par2, par3, par4);
    099
    100                    if (var20 == EnumStatus.OK)
    101                    {
    102                        setBedOccupied(par1World, par2, par3, par4, true);
    103                        return true;
    104                    }
    105                    else
    106                    {
    107                        if (var20 == EnumStatus.NOT_POSSIBLE_NOW)
    108                        {
    109                            par5EntityPlayer.addChatMessage("tile.bed.noSleep");
    110                        }
    111                        else if (var20 == EnumStatus.NOT_SAFE)
    112                        {
    113                            par5EntityPlayer.addChatMessage("tile.bed.notSafe");
    114                        }
    115
    116                        return true;
    117                    }
    118                }
    119            }
    120        }
    121
    122        /**
    123         * From the specified side and block metadata retrieves the blocks texture. Args: side, metadata
    124         */
    125        public int getBlockTextureFromSideAndMetadata(int par1, int par2)
    126        {
    127            if (par1 == 0)
    128            {
    129                return Block.planks.blockIndexInTexture;
    130            }
    131            else
    132            {
    133                int var3 = getDirection(par2);
    134                int var4 = Direction.bedDirection[var3][par1];
    135                return isBlockHeadOfBed(par2) ? (var4 == 2 ? this.blockIndexInTexture + 2 + 16 : (var4 != 5 && var4 != 4 ? this.blockIndexInTexture + 1 : this.blockIndexInTexture + 1 + 16)) : (var4 == 3 ? this.blockIndexInTexture - 1 + 16 : (var4 != 5 && var4 != 4 ? this.blockIndexInTexture : this.blockIndexInTexture + 16));
    136            }
    137        }
    138
    139        /**
    140         * The type of render function that is called for this block
    141         */
    142        public int getRenderType()
    143        {
    144            return 14;
    145        }
    146
    147        /**
    148         * If this block doesn't render as an ordinary block it will return False (examples: signs, buttons, stairs, etc)
    149         */
    150        public boolean renderAsNormalBlock()
    151        {
    152            return false;
    153        }
    154
    155        /**
    156         * Is this block (a) opaque and (b) a full 1m cube?  This determines whether or not to render the shared face of two
    157         * adjacent blocks and also whether the player can attach torches, redstone wire, etc to this block.
    158         */
    159        public boolean isOpaqueCube()
    160        {
    161            return false;
    162        }
    163
    164        /**
    165         * Updates the blocks bounds based on its current state. Args: world, x, y, z
    166         */
    167        public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4)
    168        {
    169            this.setBounds();
    170        }
    171
    172        /**
    173         * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are
    174         * their own) Args: x, y, z, neighbor blockID
    175         */
    176        public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5)
    177        {
    178            int var6 = par1World.getBlockMetadata(par2, par3, par4);
    179            int var7 = getDirection(var6);
    180
    181            if (isBlockHeadOfBed(var6))
    182            {
    183                if (par1World.getBlockId(par2 - footBlockToHeadBlockMap[var7][0], par3, par4 - footBlockToHeadBlockMap[var7][1]) != this.blockID)
    184                {
    185                    par1World.setBlockWithNotify(par2, par3, par4, 0);
    186                }
    187            }
    188            else if (par1World.getBlockId(par2 + footBlockToHeadBlockMap[var7][0], par3, par4 + footBlockToHeadBlockMap[var7][1]) != this.blockID)
    189            {
    190                par1World.setBlockWithNotify(par2, par3, par4, 0);
    191
    192                if (!par1World.isRemote)
    193                {
    194                    this.dropBlockAsItem(par1World, par2, par3, par4, var6, 0);
    195                }
    196            }
    197        }
    198
    199        /**
    200         * Returns the ID of the items to drop on destruction.
    201         */
    202        public int idDropped(int par1, Random par2Random, int par3)
    203        {
    204            return isBlockHeadOfBed(par1) ? 0 : Item.bed.shiftedIndex;
    205        }
    206
    207        /**
    208         * Set the bounds of the bed block.
    209         */
    210        private void setBounds()
    211        {
    212            this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.5625F, 1.0F);
    213        }
    214
    215        /**
    216         * Returns whether or not this bed block is the head of the bed.
    217         */
    218        public static boolean isBlockHeadOfBed(int par0)
    219        {
    220            return (par0 & 8) != 0;
    221        }
    222
    223        /**
    224         * Return whether or not the bed is occupied.
    225         */
    226        public static boolean isBedOccupied(int par0)
    227        {
    228            return (par0 & 4) != 0;
    229        }
    230
    231        /**
    232         * Sets whether or not the bed is occupied.
    233         */
    234        public static void setBedOccupied(World par0World, int par1, int par2, int par3, boolean par4)
    235        {
    236            int var5 = par0World.getBlockMetadata(par1, par2, par3);
    237
    238            if (par4)
    239            {
    240                var5 |= 4;
    241            }
    242            else
    243            {
    244                var5 &= -5;
    245            }
    246
    247            par0World.setBlockMetadataWithNotify(par1, par2, par3, var5);
    248        }
    249
    250        /**
    251         * Gets the nearest empty chunk coordinates for the player to wake up from a bed into.
    252         */
    253        public static ChunkCoordinates getNearestEmptyChunkCoordinates(World par0World, int par1, int par2, int par3, int par4)
    254        {
    255            int var5 = par0World.getBlockMetadata(par1, par2, par3);
    256            int var6 = BlockDirectional.getDirection(var5);
    257
    258            for (int var7 = 0; var7 <= 1; ++var7)
    259            {
    260                int var8 = par1 - footBlockToHeadBlockMap[var6][0] * var7 - 1;
    261                int var9 = par3 - footBlockToHeadBlockMap[var6][1] * var7 - 1;
    262                int var10 = var8 + 2;
    263                int var11 = var9 + 2;
    264
    265                for (int var12 = var8; var12 <= var10; ++var12)
    266                {
    267                    for (int var13 = var9; var13 <= var11; ++var13)
    268                    {
    269                        if (par0World.doesBlockHaveSolidTopSurface(var12, par2 - 1, var13) && par0World.isAirBlock(var12, par2, var13) && par0World.isAirBlock(var12, par2 + 1, var13))
    270                        {
    271                            if (par4 <= 0)
    272                            {
    273                                return new ChunkCoordinates(var12, par2, var13);
    274                            }
    275
    276                            --par4;
    277                        }
    278                    }
    279                }
    280            }
    281
    282            return null;
    283        }
    284
    285        /**
    286         * Drops the block items with a specified chance of dropping the specified items
    287         */
    288        public void dropBlockAsItemWithChance(World par1World, int par2, int par3, int par4, int par5, float par6, int par7)
    289        {
    290            if (!isBlockHeadOfBed(par5))
    291            {
    292                super.dropBlockAsItemWithChance(par1World, par2, par3, par4, par5, par6, 0);
    293            }
    294        }
    295
    296        /**
    297         * Returns the mobility information of the block, 0 = free, 1 = can't push but can move over, 2 = total immobility
    298         * and stop pistons
    299         */
    300        public int getMobilityFlag()
    301        {
    302            return 1;
    303        }
    304
    305        @SideOnly(Side.CLIENT)
    306
    307        /**
    308         * only called by clickMiddleMouseButton , and passed to inventory.setCurrentItem (along with isCreative)
    309         */
    310        public int idPicked(World par1World, int par2, int par3, int par4)
    311        {
    312            return Item.bed.shiftedIndex;
    313        }
    314    }