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); 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 }