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 }