001 package net.minecraft.src; 002 003 import java.util.Iterator; 004 import java.util.List; 005 006 public class TileEntityChest extends TileEntity implements IInventory 007 { 008 private ItemStack[] chestContents = new ItemStack[36]; 009 010 /** Determines if the check for adjacent chests has taken place. */ 011 public boolean adjacentChestChecked = false; 012 013 /** Contains the chest tile located adjacent to this one (if any) */ 014 public TileEntityChest adjacentChestZNeg; 015 016 /** Contains the chest tile located adjacent to this one (if any) */ 017 public TileEntityChest adjacentChestXPos; 018 019 /** Contains the chest tile located adjacent to this one (if any) */ 020 public TileEntityChest adjacentChestXNeg; 021 022 /** Contains the chest tile located adjacent to this one (if any) */ 023 public TileEntityChest adjacentChestZPosition; 024 025 /** The current angle of the lid (between 0 and 1) */ 026 public float lidAngle; 027 028 /** The angle of the lid last tick */ 029 public float prevLidAngle; 030 031 /** The number of players currently using this chest */ 032 public int numUsingPlayers; 033 034 /** Server sync counter (once per 20 ticks) */ 035 private int ticksSinceSync; 036 037 /** 038 * Returns the number of slots in the inventory. 039 */ 040 public int getSizeInventory() 041 { 042 return 27; 043 } 044 045 /** 046 * Returns the stack in slot i 047 */ 048 public ItemStack getStackInSlot(int par1) 049 { 050 return this.chestContents[par1]; 051 } 052 053 /** 054 * Removes from an inventory slot (first arg) up to a specified number (second arg) of items and returns them in a 055 * new stack. 056 */ 057 public ItemStack decrStackSize(int par1, int par2) 058 { 059 if (this.chestContents[par1] != null) 060 { 061 ItemStack var3; 062 063 if (this.chestContents[par1].stackSize <= par2) 064 { 065 var3 = this.chestContents[par1]; 066 this.chestContents[par1] = null; 067 this.onInventoryChanged(); 068 return var3; 069 } 070 else 071 { 072 var3 = this.chestContents[par1].splitStack(par2); 073 074 if (this.chestContents[par1].stackSize == 0) 075 { 076 this.chestContents[par1] = null; 077 } 078 079 this.onInventoryChanged(); 080 return var3; 081 } 082 } 083 else 084 { 085 return null; 086 } 087 } 088 089 /** 090 * When some containers are closed they call this on each slot, then drop whatever it returns as an EntityItem - 091 * like when you close a workbench GUI. 092 */ 093 public ItemStack getStackInSlotOnClosing(int par1) 094 { 095 if (this.chestContents[par1] != null) 096 { 097 ItemStack var2 = this.chestContents[par1]; 098 this.chestContents[par1] = null; 099 return var2; 100 } 101 else 102 { 103 return null; 104 } 105 } 106 107 /** 108 * Sets the given item stack to the specified slot in the inventory (can be crafting or armor sections). 109 */ 110 public void setInventorySlotContents(int par1, ItemStack par2ItemStack) 111 { 112 this.chestContents[par1] = par2ItemStack; 113 114 if (par2ItemStack != null && par2ItemStack.stackSize > this.getInventoryStackLimit()) 115 { 116 par2ItemStack.stackSize = this.getInventoryStackLimit(); 117 } 118 119 this.onInventoryChanged(); 120 } 121 122 /** 123 * Returns the name of the inventory. 124 */ 125 public String getInvName() 126 { 127 return "container.chest"; 128 } 129 130 /** 131 * Reads a tile entity from NBT. 132 */ 133 public void readFromNBT(NBTTagCompound par1NBTTagCompound) 134 { 135 super.readFromNBT(par1NBTTagCompound); 136 NBTTagList var2 = par1NBTTagCompound.getTagList("Items"); 137 this.chestContents = new ItemStack[this.getSizeInventory()]; 138 139 for (int var3 = 0; var3 < var2.tagCount(); ++var3) 140 { 141 NBTTagCompound var4 = (NBTTagCompound)var2.tagAt(var3); 142 int var5 = var4.getByte("Slot") & 255; 143 144 if (var5 >= 0 && var5 < this.chestContents.length) 145 { 146 this.chestContents[var5] = ItemStack.loadItemStackFromNBT(var4); 147 } 148 } 149 } 150 151 /** 152 * Writes a tile entity to NBT. 153 */ 154 public void writeToNBT(NBTTagCompound par1NBTTagCompound) 155 { 156 super.writeToNBT(par1NBTTagCompound); 157 NBTTagList var2 = new NBTTagList(); 158 159 for (int var3 = 0; var3 < this.chestContents.length; ++var3) 160 { 161 if (this.chestContents[var3] != null) 162 { 163 NBTTagCompound var4 = new NBTTagCompound(); 164 var4.setByte("Slot", (byte)var3); 165 this.chestContents[var3].writeToNBT(var4); 166 var2.appendTag(var4); 167 } 168 } 169 170 par1NBTTagCompound.setTag("Items", var2); 171 } 172 173 /** 174 * Returns the maximum stack size for a inventory slot. Seems to always be 64, possibly will be extended. *Isn't 175 * this more of a set than a get?* 176 */ 177 public int getInventoryStackLimit() 178 { 179 return 64; 180 } 181 182 /** 183 * Do not make give this method the name canInteractWith because it clashes with Container 184 */ 185 public boolean isUseableByPlayer(EntityPlayer par1EntityPlayer) 186 { 187 return this.worldObj.getBlockTileEntity(this.xCoord, this.yCoord, this.zCoord) != this ? false : par1EntityPlayer.getDistanceSq((double)this.xCoord + 0.5D, (double)this.yCoord + 0.5D, (double)this.zCoord + 0.5D) <= 64.0D; 188 } 189 190 /** 191 * Causes the TileEntity to reset all it's cached values for it's container block, blockID, metaData and in the case 192 * of chests, the adjcacent chest check 193 */ 194 public void updateContainingBlockInfo() 195 { 196 super.updateContainingBlockInfo(); 197 this.adjacentChestChecked = false; 198 } 199 200 /** 201 * Performs the check for adjacent chests to determine if this chest is double or not. 202 */ 203 public void checkForAdjacentChests() 204 { 205 if (!this.adjacentChestChecked) 206 { 207 this.adjacentChestChecked = true; 208 this.adjacentChestZNeg = null; 209 this.adjacentChestXPos = null; 210 this.adjacentChestXNeg = null; 211 this.adjacentChestZPosition = null; 212 213 if (this.worldObj.getBlockId(this.xCoord - 1, this.yCoord, this.zCoord) == Block.chest.blockID) 214 { 215 this.adjacentChestXNeg = (TileEntityChest)this.worldObj.getBlockTileEntity(this.xCoord - 1, this.yCoord, this.zCoord); 216 } 217 218 if (this.worldObj.getBlockId(this.xCoord + 1, this.yCoord, this.zCoord) == Block.chest.blockID) 219 { 220 this.adjacentChestXPos = (TileEntityChest)this.worldObj.getBlockTileEntity(this.xCoord + 1, this.yCoord, this.zCoord); 221 } 222 223 if (this.worldObj.getBlockId(this.xCoord, this.yCoord, this.zCoord - 1) == Block.chest.blockID) 224 { 225 this.adjacentChestZNeg = (TileEntityChest)this.worldObj.getBlockTileEntity(this.xCoord, this.yCoord, this.zCoord - 1); 226 } 227 228 if (this.worldObj.getBlockId(this.xCoord, this.yCoord, this.zCoord + 1) == Block.chest.blockID) 229 { 230 this.adjacentChestZPosition = (TileEntityChest)this.worldObj.getBlockTileEntity(this.xCoord, this.yCoord, this.zCoord + 1); 231 } 232 233 if (this.adjacentChestZNeg != null) 234 { 235 this.adjacentChestZNeg.updateContainingBlockInfo(); 236 } 237 238 if (this.adjacentChestZPosition != null) 239 { 240 this.adjacentChestZPosition.updateContainingBlockInfo(); 241 } 242 243 if (this.adjacentChestXPos != null) 244 { 245 this.adjacentChestXPos.updateContainingBlockInfo(); 246 } 247 248 if (this.adjacentChestXNeg != null) 249 { 250 this.adjacentChestXNeg.updateContainingBlockInfo(); 251 } 252 } 253 } 254 255 /** 256 * Allows the entity to update its state. Overridden in most subclasses, e.g. the mob spawner uses this to count 257 * ticks and creates a new spawn inside its implementation. 258 */ 259 public void updateEntity() 260 { 261 super.updateEntity(); 262 this.checkForAdjacentChests(); 263 ++this.ticksSinceSync; 264 float var1; 265 266 if (!this.worldObj.isRemote && this.numUsingPlayers != 0 && (this.ticksSinceSync + this.xCoord + this.yCoord + this.zCoord) % 200 == 0) 267 { 268 this.numUsingPlayers = 0; 269 var1 = 5.0F; 270 List var2 = this.worldObj.getEntitiesWithinAABB(EntityPlayer.class, AxisAlignedBB.getAABBPool().addOrModifyAABBInPool((double)((float)this.xCoord - var1), (double)((float)this.yCoord - var1), (double)((float)this.zCoord - var1), (double)((float)(this.xCoord + 1) + var1), (double)((float)(this.yCoord + 1) + var1), (double)((float)(this.zCoord + 1) + var1))); 271 Iterator var3 = var2.iterator(); 272 273 while (var3.hasNext()) 274 { 275 EntityPlayer var4 = (EntityPlayer)var3.next(); 276 277 if (var4.craftingInventory instanceof ContainerChest && ((ContainerChest)var4.craftingInventory).func_85151_d() == this) 278 { 279 ++this.numUsingPlayers; 280 } 281 } 282 } 283 284 this.prevLidAngle = this.lidAngle; 285 var1 = 0.1F; 286 double var11; 287 288 if (this.numUsingPlayers > 0 && this.lidAngle == 0.0F && this.adjacentChestZNeg == null && this.adjacentChestXNeg == null) 289 { 290 double var8 = (double)this.xCoord + 0.5D; 291 var11 = (double)this.zCoord + 0.5D; 292 293 if (this.adjacentChestZPosition != null) 294 { 295 var11 += 0.5D; 296 } 297 298 if (this.adjacentChestXPos != null) 299 { 300 var8 += 0.5D; 301 } 302 303 this.worldObj.playSoundEffect(var8, (double)this.yCoord + 0.5D, var11, "random.chestopen", 0.5F, this.worldObj.rand.nextFloat() * 0.1F + 0.9F); 304 } 305 306 if (this.numUsingPlayers == 0 && this.lidAngle > 0.0F || this.numUsingPlayers > 0 && this.lidAngle < 1.0F) 307 { 308 float var9 = this.lidAngle; 309 310 if (this.numUsingPlayers > 0) 311 { 312 this.lidAngle += var1; 313 } 314 else 315 { 316 this.lidAngle -= var1; 317 } 318 319 if (this.lidAngle > 1.0F) 320 { 321 this.lidAngle = 1.0F; 322 } 323 324 float var10 = 0.5F; 325 326 if (this.lidAngle < var10 && var9 >= var10 && this.adjacentChestZNeg == null && this.adjacentChestXNeg == null) 327 { 328 var11 = (double)this.xCoord + 0.5D; 329 double var6 = (double)this.zCoord + 0.5D; 330 331 if (this.adjacentChestZPosition != null) 332 { 333 var6 += 0.5D; 334 } 335 336 if (this.adjacentChestXPos != null) 337 { 338 var11 += 0.5D; 339 } 340 341 this.worldObj.playSoundEffect(var11, (double)this.yCoord + 0.5D, var6, "random.chestclosed", 0.5F, this.worldObj.rand.nextFloat() * 0.1F + 0.9F); 342 } 343 344 if (this.lidAngle < 0.0F) 345 { 346 this.lidAngle = 0.0F; 347 } 348 } 349 } 350 351 /** 352 * Called when a client event is received with the event number and argument, see World.sendClientEvent 353 */ 354 public void receiveClientEvent(int par1, int par2) 355 { 356 if (par1 == 1) 357 { 358 this.numUsingPlayers = par2; 359 } 360 } 361 362 public void openChest() 363 { 364 ++this.numUsingPlayers; 365 this.worldObj.addBlockEvent(this.xCoord, this.yCoord, this.zCoord, Block.chest.blockID, 1, this.numUsingPlayers); 366 } 367 368 public void closeChest() 369 { 370 --this.numUsingPlayers; 371 this.worldObj.addBlockEvent(this.xCoord, this.yCoord, this.zCoord, Block.chest.blockID, 1, this.numUsingPlayers); 372 } 373 374 /** 375 * invalidates a tile entity 376 */ 377 public void invalidate() 378 { 379 this.updateContainingBlockInfo(); 380 this.checkForAdjacentChests(); 381 super.invalidate(); 382 } 383 }