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 import static net.minecraftforge.common.ForgeDirection.*; 008 009 public class BlockChest extends BlockContainer 010 { 011 private Random random = new Random(); 012 013 protected BlockChest(int par1) 014 { 015 super(par1, Material.wood); 016 this.blockIndexInTexture = 26; 017 this.setCreativeTab(CreativeTabs.tabDecorations); 018 this.setBlockBounds(0.0625F, 0.0F, 0.0625F, 0.9375F, 0.875F, 0.9375F); 019 } 020 021 /** 022 * Is this block (a) opaque and (b) a full 1m cube? This determines whether or not to render the shared face of two 023 * adjacent blocks and also whether the player can attach torches, redstone wire, etc to this block. 024 */ 025 public boolean isOpaqueCube() 026 { 027 return false; 028 } 029 030 /** 031 * If this block doesn't render as an ordinary block it will return False (examples: signs, buttons, stairs, etc) 032 */ 033 public boolean renderAsNormalBlock() 034 { 035 return false; 036 } 037 038 /** 039 * The type of render function that is called for this block 040 */ 041 public int getRenderType() 042 { 043 return 22; 044 } 045 046 /** 047 * Updates the blocks bounds based on its current state. Args: world, x, y, z 048 */ 049 public void setBlockBoundsBasedOnState(IBlockAccess par1IBlockAccess, int par2, int par3, int par4) 050 { 051 if (par1IBlockAccess.getBlockId(par2, par3, par4 - 1) == this.blockID) 052 { 053 this.setBlockBounds(0.0625F, 0.0F, 0.0F, 0.9375F, 0.875F, 0.9375F); 054 } 055 else if (par1IBlockAccess.getBlockId(par2, par3, par4 + 1) == this.blockID) 056 { 057 this.setBlockBounds(0.0625F, 0.0F, 0.0625F, 0.9375F, 0.875F, 1.0F); 058 } 059 else if (par1IBlockAccess.getBlockId(par2 - 1, par3, par4) == this.blockID) 060 { 061 this.setBlockBounds(0.0F, 0.0F, 0.0625F, 0.9375F, 0.875F, 0.9375F); 062 } 063 else if (par1IBlockAccess.getBlockId(par2 + 1, par3, par4) == this.blockID) 064 { 065 this.setBlockBounds(0.0625F, 0.0F, 0.0625F, 1.0F, 0.875F, 0.9375F); 066 } 067 else 068 { 069 this.setBlockBounds(0.0625F, 0.0F, 0.0625F, 0.9375F, 0.875F, 0.9375F); 070 } 071 } 072 073 /** 074 * Called whenever the block is added into the world. Args: world, x, y, z 075 */ 076 public void onBlockAdded(World par1World, int par2, int par3, int par4) 077 { 078 super.onBlockAdded(par1World, par2, par3, par4); 079 this.unifyAdjacentChests(par1World, par2, par3, par4); 080 int var5 = par1World.getBlockId(par2, par3, par4 - 1); 081 int var6 = par1World.getBlockId(par2, par3, par4 + 1); 082 int var7 = par1World.getBlockId(par2 - 1, par3, par4); 083 int var8 = par1World.getBlockId(par2 + 1, par3, par4); 084 085 if (var5 == this.blockID) 086 { 087 this.unifyAdjacentChests(par1World, par2, par3, par4 - 1); 088 } 089 090 if (var6 == this.blockID) 091 { 092 this.unifyAdjacentChests(par1World, par2, par3, par4 + 1); 093 } 094 095 if (var7 == this.blockID) 096 { 097 this.unifyAdjacentChests(par1World, par2 - 1, par3, par4); 098 } 099 100 if (var8 == this.blockID) 101 { 102 this.unifyAdjacentChests(par1World, par2 + 1, par3, par4); 103 } 104 } 105 106 /** 107 * Called when the block is placed in the world. 108 */ 109 public void onBlockPlacedBy(World par1World, int par2, int par3, int par4, EntityLiving par5EntityLiving) 110 { 111 int var6 = par1World.getBlockId(par2, par3, par4 - 1); 112 int var7 = par1World.getBlockId(par2, par3, par4 + 1); 113 int var8 = par1World.getBlockId(par2 - 1, par3, par4); 114 int var9 = par1World.getBlockId(par2 + 1, par3, par4); 115 byte var10 = 0; 116 int var11 = MathHelper.floor_double((double)(par5EntityLiving.rotationYaw * 4.0F / 360.0F) + 0.5D) & 3; 117 118 if (var11 == 0) 119 { 120 var10 = 2; 121 } 122 123 if (var11 == 1) 124 { 125 var10 = 5; 126 } 127 128 if (var11 == 2) 129 { 130 var10 = 3; 131 } 132 133 if (var11 == 3) 134 { 135 var10 = 4; 136 } 137 138 if (var6 != this.blockID && var7 != this.blockID && var8 != this.blockID && var9 != this.blockID) 139 { 140 par1World.setBlockMetadataWithNotify(par2, par3, par4, var10); 141 } 142 else 143 { 144 if ((var6 == this.blockID || var7 == this.blockID) && (var10 == 4 || var10 == 5)) 145 { 146 if (var6 == this.blockID) 147 { 148 par1World.setBlockMetadataWithNotify(par2, par3, par4 - 1, var10); 149 } 150 else 151 { 152 par1World.setBlockMetadataWithNotify(par2, par3, par4 + 1, var10); 153 } 154 155 par1World.setBlockMetadataWithNotify(par2, par3, par4, var10); 156 } 157 158 if ((var8 == this.blockID || var9 == this.blockID) && (var10 == 2 || var10 == 3)) 159 { 160 if (var8 == this.blockID) 161 { 162 par1World.setBlockMetadataWithNotify(par2 - 1, par3, par4, var10); 163 } 164 else 165 { 166 par1World.setBlockMetadataWithNotify(par2 + 1, par3, par4, var10); 167 } 168 169 par1World.setBlockMetadataWithNotify(par2, par3, par4, var10); 170 } 171 } 172 } 173 174 /** 175 * Turns the adjacent chests to a double chest. 176 */ 177 public void unifyAdjacentChests(World par1World, int par2, int par3, int par4) 178 { 179 if (!par1World.isRemote) 180 { 181 int var5 = par1World.getBlockId(par2, par3, par4 - 1); 182 int var6 = par1World.getBlockId(par2, par3, par4 + 1); 183 int var7 = par1World.getBlockId(par2 - 1, par3, par4); 184 int var8 = par1World.getBlockId(par2 + 1, par3, par4); 185 boolean var9 = true; 186 int var10; 187 int var11; 188 boolean var12; 189 byte var13; 190 int var14; 191 192 if (var5 != this.blockID && var6 != this.blockID) 193 { 194 if (var7 != this.blockID && var8 != this.blockID) 195 { 196 var13 = 3; 197 198 if (Block.opaqueCubeLookup[var5] && !Block.opaqueCubeLookup[var6]) 199 { 200 var13 = 3; 201 } 202 203 if (Block.opaqueCubeLookup[var6] && !Block.opaqueCubeLookup[var5]) 204 { 205 var13 = 2; 206 } 207 208 if (Block.opaqueCubeLookup[var7] && !Block.opaqueCubeLookup[var8]) 209 { 210 var13 = 5; 211 } 212 213 if (Block.opaqueCubeLookup[var8] && !Block.opaqueCubeLookup[var7]) 214 { 215 var13 = 4; 216 } 217 } 218 else 219 { 220 var10 = par1World.getBlockId(var7 == this.blockID ? par2 - 1 : par2 + 1, par3, par4 - 1); 221 var11 = par1World.getBlockId(var7 == this.blockID ? par2 - 1 : par2 + 1, par3, par4 + 1); 222 var13 = 3; 223 var12 = true; 224 225 if (var7 == this.blockID) 226 { 227 var14 = par1World.getBlockMetadata(par2 - 1, par3, par4); 228 } 229 else 230 { 231 var14 = par1World.getBlockMetadata(par2 + 1, par3, par4); 232 } 233 234 if (var14 == 2) 235 { 236 var13 = 2; 237 } 238 239 if ((Block.opaqueCubeLookup[var5] || Block.opaqueCubeLookup[var10]) && !Block.opaqueCubeLookup[var6] && !Block.opaqueCubeLookup[var11]) 240 { 241 var13 = 3; 242 } 243 244 if ((Block.opaqueCubeLookup[var6] || Block.opaqueCubeLookup[var11]) && !Block.opaqueCubeLookup[var5] && !Block.opaqueCubeLookup[var10]) 245 { 246 var13 = 2; 247 } 248 } 249 } 250 else 251 { 252 var10 = par1World.getBlockId(par2 - 1, par3, var5 == this.blockID ? par4 - 1 : par4 + 1); 253 var11 = par1World.getBlockId(par2 + 1, par3, var5 == this.blockID ? par4 - 1 : par4 + 1); 254 var13 = 5; 255 var12 = true; 256 257 if (var5 == this.blockID) 258 { 259 var14 = par1World.getBlockMetadata(par2, par3, par4 - 1); 260 } 261 else 262 { 263 var14 = par1World.getBlockMetadata(par2, par3, par4 + 1); 264 } 265 266 if (var14 == 4) 267 { 268 var13 = 4; 269 } 270 271 if ((Block.opaqueCubeLookup[var7] || Block.opaqueCubeLookup[var10]) && !Block.opaqueCubeLookup[var8] && !Block.opaqueCubeLookup[var11]) 272 { 273 var13 = 5; 274 } 275 276 if ((Block.opaqueCubeLookup[var8] || Block.opaqueCubeLookup[var11]) && !Block.opaqueCubeLookup[var7] && !Block.opaqueCubeLookup[var10]) 277 { 278 var13 = 4; 279 } 280 } 281 282 par1World.setBlockMetadataWithNotify(par2, par3, par4, var13); 283 } 284 } 285 286 @SideOnly(Side.CLIENT) 287 288 /** 289 * Retrieves the block texture to use based on the display side. Args: iBlockAccess, x, y, z, side 290 */ 291 public int getBlockTexture(IBlockAccess par1IBlockAccess, int par2, int par3, int par4, int par5) 292 { 293 return 4; 294 } 295 296 /** 297 * Returns the block texture based on the side being looked at. Args: side 298 */ 299 public int getBlockTextureFromSide(int par1) 300 { 301 return 4; 302 } 303 304 /** 305 * Checks to see if its valid to put this block at the specified coordinates. Args: world, x, y, z 306 */ 307 public boolean canPlaceBlockAt(World par1World, int par2, int par3, int par4) 308 { 309 int var5 = 0; 310 311 if (par1World.getBlockId(par2 - 1, par3, par4) == this.blockID) 312 { 313 ++var5; 314 } 315 316 if (par1World.getBlockId(par2 + 1, par3, par4) == this.blockID) 317 { 318 ++var5; 319 } 320 321 if (par1World.getBlockId(par2, par3, par4 - 1) == this.blockID) 322 { 323 ++var5; 324 } 325 326 if (par1World.getBlockId(par2, par3, par4 + 1) == this.blockID) 327 { 328 ++var5; 329 } 330 331 return var5 > 1 ? false : (this.isThereANeighborChest(par1World, par2 - 1, par3, par4) ? false : (this.isThereANeighborChest(par1World, par2 + 1, par3, par4) ? false : (this.isThereANeighborChest(par1World, par2, par3, par4 - 1) ? false : !this.isThereANeighborChest(par1World, par2, par3, par4 + 1)))); 332 } 333 334 /** 335 * Checks the neighbor blocks to see if there is a chest there. Args: world, x, y, z 336 */ 337 private boolean isThereANeighborChest(World par1World, int par2, int par3, int par4) 338 { 339 return par1World.getBlockId(par2, par3, par4) != this.blockID ? false : (par1World.getBlockId(par2 - 1, par3, par4) == this.blockID ? true : (par1World.getBlockId(par2 + 1, par3, par4) == this.blockID ? true : (par1World.getBlockId(par2, par3, par4 - 1) == this.blockID ? true : par1World.getBlockId(par2, par3, par4 + 1) == this.blockID))); 340 } 341 342 /** 343 * Lets the block know when one of its neighbor changes. Doesn't know which neighbor changed (coordinates passed are 344 * their own) Args: x, y, z, neighbor blockID 345 */ 346 public void onNeighborBlockChange(World par1World, int par2, int par3, int par4, int par5) 347 { 348 super.onNeighborBlockChange(par1World, par2, par3, par4, par5); 349 TileEntityChest var6 = (TileEntityChest)par1World.getBlockTileEntity(par2, par3, par4); 350 351 if (var6 != null) 352 { 353 var6.updateContainingBlockInfo(); 354 } 355 } 356 357 /** 358 * ejects contained items into the world, and notifies neighbours of an update, as appropriate 359 */ 360 public void breakBlock(World par1World, int par2, int par3, int par4, int par5, int par6) 361 { 362 TileEntityChest var7 = (TileEntityChest)par1World.getBlockTileEntity(par2, par3, par4); 363 364 if (var7 != null) 365 { 366 for (int var8 = 0; var8 < var7.getSizeInventory(); ++var8) 367 { 368 ItemStack var9 = var7.getStackInSlot(var8); 369 370 if (var9 != null) 371 { 372 float var10 = this.random.nextFloat() * 0.8F + 0.1F; 373 float var11 = this.random.nextFloat() * 0.8F + 0.1F; 374 EntityItem var14; 375 376 for (float var12 = this.random.nextFloat() * 0.8F + 0.1F; var9.stackSize > 0; par1World.spawnEntityInWorld(var14)) 377 { 378 int var13 = this.random.nextInt(21) + 10; 379 380 if (var13 > var9.stackSize) 381 { 382 var13 = var9.stackSize; 383 } 384 385 var9.stackSize -= var13; 386 var14 = new EntityItem(par1World, (double)((float)par2 + var10), (double)((float)par3 + var11), (double)((float)par4 + var12), new ItemStack(var9.itemID, var13, var9.getItemDamage())); 387 float var15 = 0.05F; 388 var14.motionX = (double)((float)this.random.nextGaussian() * var15); 389 var14.motionY = (double)((float)this.random.nextGaussian() * var15 + 0.2F); 390 var14.motionZ = (double)((float)this.random.nextGaussian() * var15); 391 392 if (var9.hasTagCompound()) 393 { 394 var14.item.setTagCompound((NBTTagCompound)var9.getTagCompound().copy()); 395 } 396 } 397 } 398 } 399 } 400 401 super.breakBlock(par1World, par2, par3, par4, par5, par6); 402 } 403 404 /** 405 * Called upon block activation (right click on the block.) 406 */ 407 public boolean onBlockActivated(World par1World, int par2, int par3, int par4, EntityPlayer par5EntityPlayer, int par6, float par7, float par8, float par9) 408 { 409 Object var10 = (TileEntityChest)par1World.getBlockTileEntity(par2, par3, par4); 410 411 if (var10 == null) 412 { 413 return true; 414 } 415 else if (par1World.isBlockSolidOnSide(par2, par3 + 1, par4, DOWN)) 416 { 417 return true; 418 } 419 else if (isOcelotBlockingChest(par1World, par2, par3, par4)) 420 { 421 return true; 422 } 423 else if (par1World.getBlockId(par2 - 1, par3, par4) == this.blockID && (par1World.isBlockSolidOnSide(par2 - 1, par3 + 1, par4, DOWN) || isOcelotBlockingChest(par1World, par2 - 1, par3, par4))) 424 { 425 return true; 426 } 427 else if (par1World.getBlockId(par2 + 1, par3, par4) == this.blockID && (par1World.isBlockSolidOnSide(par2 + 1, par3 + 1, par4, DOWN) || isOcelotBlockingChest(par1World, par2 + 1, par3, par4))) 428 { 429 return true; 430 } 431 else if (par1World.getBlockId(par2, par3, par4 - 1) == this.blockID && (par1World.isBlockSolidOnSide(par2, par3 + 1, par4 - 1, DOWN) || isOcelotBlockingChest(par1World, par2, par3, par4 - 1))) 432 { 433 return true; 434 } 435 else if (par1World.getBlockId(par2, par3, par4 + 1) == this.blockID && (par1World.isBlockSolidOnSide(par2, par3 + 1, par4 + 1, DOWN) || isOcelotBlockingChest(par1World, par2, par3, par4 + 1))) 436 { 437 return true; 438 } 439 else 440 { 441 if (par1World.getBlockId(par2 - 1, par3, par4) == this.blockID) 442 { 443 var10 = new InventoryLargeChest("container.chestDouble", (TileEntityChest)par1World.getBlockTileEntity(par2 - 1, par3, par4), (IInventory)var10); 444 } 445 446 if (par1World.getBlockId(par2 + 1, par3, par4) == this.blockID) 447 { 448 var10 = new InventoryLargeChest("container.chestDouble", (IInventory)var10, (TileEntityChest)par1World.getBlockTileEntity(par2 + 1, par3, par4)); 449 } 450 451 if (par1World.getBlockId(par2, par3, par4 - 1) == this.blockID) 452 { 453 var10 = new InventoryLargeChest("container.chestDouble", (TileEntityChest)par1World.getBlockTileEntity(par2, par3, par4 - 1), (IInventory)var10); 454 } 455 456 if (par1World.getBlockId(par2, par3, par4 + 1) == this.blockID) 457 { 458 var10 = new InventoryLargeChest("container.chestDouble", (IInventory)var10, (TileEntityChest)par1World.getBlockTileEntity(par2, par3, par4 + 1)); 459 } 460 461 if (par1World.isRemote) 462 { 463 return true; 464 } 465 else 466 { 467 par5EntityPlayer.displayGUIChest((IInventory)var10); 468 return true; 469 } 470 } 471 } 472 473 /** 474 * Returns a new instance of a block's tile entity class. Called on placing the block. 475 */ 476 public TileEntity createNewTileEntity(World par1World) 477 { 478 return new TileEntityChest(); 479 } 480 481 /** 482 * Looks for a sitting ocelot within certain bounds. Such an ocelot is considered to be blocking access to the 483 * chest. 484 */ 485 public static boolean isOcelotBlockingChest(World par0World, int par1, int par2, int par3) 486 { 487 Iterator var4 = par0World.getEntitiesWithinAABB(EntityOcelot.class, AxisAlignedBB.getAABBPool().addOrModifyAABBInPool((double)par1, (double)(par2 + 1), (double)par3, (double)(par1 + 1), (double)(par2 + 2), (double)(par3 + 1))).iterator(); 488 EntityOcelot var6; 489 490 do 491 { 492 if (!var4.hasNext()) 493 { 494 return false; 495 } 496 497 EntityOcelot var5 = (EntityOcelot)var4.next(); 498 var6 = (EntityOcelot)var5; 499 } 500 while (!var6.isSitting()); 501 502 return true; 503 } 504 }