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