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.ArrayList;
006 import java.util.HashSet;
007 import java.util.List;
008 import java.util.Set;
009
010 public abstract class Container
011 {
012 /** the list of all items(stacks) for the corresponding slot */
013 public List inventoryItemStacks = new ArrayList();
014
015 /** the list of all slots in the inventory */
016 public List inventorySlots = new ArrayList();
017 public int windowId = 0;
018 private short transactionID = 0;
019
020 /**
021 * list of all people that need to be notified when this craftinventory changes
022 */
023 protected List crafters = new ArrayList();
024 private Set playerList = new HashSet();
025
026 /**
027 * the slot is assumed empty
028 */
029 protected Slot addSlotToContainer(Slot par1Slot)
030 {
031 par1Slot.slotNumber = this.inventorySlots.size();
032 this.inventorySlots.add(par1Slot);
033 this.inventoryItemStacks.add((Object)null);
034 return par1Slot;
035 }
036
037 public void addCraftingToCrafters(ICrafting par1ICrafting)
038 {
039 if (this.crafters.contains(par1ICrafting))
040 {
041 throw new IllegalArgumentException("Listener already listening");
042 }
043 else
044 {
045 this.crafters.add(par1ICrafting);
046 par1ICrafting.sendContainerAndContentsToPlayer(this, this.getInventory());
047 this.updateCraftingResults();
048 }
049 }
050
051 /**
052 * returns a list if itemStacks, for each slot.
053 */
054 public List getInventory()
055 {
056 ArrayList var1 = new ArrayList();
057
058 for (int var2 = 0; var2 < this.inventorySlots.size(); ++var2)
059 {
060 var1.add(((Slot)this.inventorySlots.get(var2)).getStack());
061 }
062
063 return var1;
064 }
065
066 @SideOnly(Side.CLIENT)
067
068 /**
069 * Remove this crafting listener from the listener list.
070 */
071 public void removeCraftingFromCrafters(ICrafting par1ICrafting)
072 {
073 this.crafters.remove(par1ICrafting);
074 }
075
076 /**
077 * Updates crafting matrix; called from onCraftMatrixChanged. Args: none
078 */
079 public void updateCraftingResults()
080 {
081 for (int var1 = 0; var1 < this.inventorySlots.size(); ++var1)
082 {
083 ItemStack var2 = ((Slot)this.inventorySlots.get(var1)).getStack();
084 ItemStack var3 = (ItemStack)this.inventoryItemStacks.get(var1);
085
086 if (!ItemStack.areItemStacksEqual(var3, var2))
087 {
088 var3 = var2 == null ? null : var2.copy();
089 this.inventoryItemStacks.set(var1, var3);
090
091 for (int var4 = 0; var4 < this.crafters.size(); ++var4)
092 {
093 ((ICrafting)this.crafters.get(var4)).updateCraftingInventorySlot(this, var1, var3);
094 }
095 }
096 }
097 }
098
099 /**
100 * enchants the item on the table using the specified slot; also deducts XP from player
101 */
102 public boolean enchantItem(EntityPlayer par1EntityPlayer, int par2)
103 {
104 return false;
105 }
106
107 public Slot getSlotFromInventory(IInventory par1IInventory, int par2)
108 {
109 for (int var3 = 0; var3 < this.inventorySlots.size(); ++var3)
110 {
111 Slot var4 = (Slot)this.inventorySlots.get(var3);
112
113 if (var4.isSlotInInventory(par1IInventory, par2))
114 {
115 return var4;
116 }
117 }
118
119 return null;
120 }
121
122 public Slot getSlot(int par1)
123 {
124 return (Slot)this.inventorySlots.get(par1);
125 }
126
127 /**
128 * Called when a player shift-clicks on a slot. You must override this or you will crash when someone does that.
129 */
130 public ItemStack transferStackInSlot(EntityPlayer par1EntityPlayer, int par2)
131 {
132 Slot var3 = (Slot)this.inventorySlots.get(par2);
133 return var3 != null ? var3.getStack() : null;
134 }
135
136 public ItemStack slotClick(int par1, int par2, int par3, EntityPlayer par4EntityPlayer)
137 {
138 ItemStack var5 = null;
139 InventoryPlayer var6 = par4EntityPlayer.inventory;
140 Slot var7;
141 ItemStack var8;
142 int var10;
143 ItemStack var11;
144
145 if ((par3 == 0 || par3 == 1) && (par2 == 0 || par2 == 1))
146 {
147 if (par1 == -999)
148 {
149 if (var6.getItemStack() != null && par1 == -999)
150 {
151 if (par2 == 0)
152 {
153 par4EntityPlayer.dropPlayerItem(var6.getItemStack());
154 var6.setItemStack((ItemStack)null);
155 }
156
157 if (par2 == 1)
158 {
159 par4EntityPlayer.dropPlayerItem(var6.getItemStack().splitStack(1));
160
161 if (var6.getItemStack().stackSize == 0)
162 {
163 var6.setItemStack((ItemStack)null);
164 }
165 }
166 }
167 }
168 else if (par3 == 1)
169 {
170 var7 = (Slot)this.inventorySlots.get(par1);
171
172 if (var7 != null && var7.canTakeStack(par4EntityPlayer))
173 {
174 var8 = this.transferStackInSlot(par4EntityPlayer, par1);
175
176 if (var8 != null)
177 {
178 int var12 = var8.itemID;
179 var5 = var8.copy();
180
181 if (var7 != null && var7.getStack() != null && var7.getStack().itemID == var12)
182 {
183 this.retrySlotClick(par1, par2, true, par4EntityPlayer);
184 }
185 }
186 }
187 }
188 else
189 {
190 if (par1 < 0)
191 {
192 return null;
193 }
194
195 var7 = (Slot)this.inventorySlots.get(par1);
196
197 if (var7 != null)
198 {
199 var8 = var7.getStack();
200 ItemStack var13 = var6.getItemStack();
201
202 if (var8 != null)
203 {
204 var5 = var8.copy();
205 }
206
207 if (var8 == null)
208 {
209 if (var13 != null && var7.isItemValid(var13))
210 {
211 var10 = par2 == 0 ? var13.stackSize : 1;
212
213 if (var10 > var7.getSlotStackLimit())
214 {
215 var10 = var7.getSlotStackLimit();
216 }
217
218 var7.putStack(var13.splitStack(var10));
219
220 if (var13.stackSize == 0)
221 {
222 var6.setItemStack((ItemStack)null);
223 }
224 }
225 }
226 else if (var7.canTakeStack(par4EntityPlayer))
227 {
228 if (var13 == null)
229 {
230 var10 = par2 == 0 ? var8.stackSize : (var8.stackSize + 1) / 2;
231 var11 = var7.decrStackSize(var10);
232 var6.setItemStack(var11);
233
234 if (var8.stackSize == 0)
235 {
236 var7.putStack((ItemStack)null);
237 }
238
239 var7.onPickupFromSlot(par4EntityPlayer, var6.getItemStack());
240 }
241 else if (var7.isItemValid(var13))
242 {
243 if (var8.itemID == var13.itemID && (!var8.getHasSubtypes() || var8.getItemDamage() == var13.getItemDamage()) && ItemStack.areItemStackTagsEqual(var8, var13))
244 {
245 var10 = par2 == 0 ? var13.stackSize : 1;
246
247 if (var10 > var7.getSlotStackLimit() - var8.stackSize)
248 {
249 var10 = var7.getSlotStackLimit() - var8.stackSize;
250 }
251
252 if (var10 > var13.getMaxStackSize() - var8.stackSize)
253 {
254 var10 = var13.getMaxStackSize() - var8.stackSize;
255 }
256
257 var13.splitStack(var10);
258
259 if (var13.stackSize == 0)
260 {
261 var6.setItemStack((ItemStack)null);
262 }
263
264 var8.stackSize += var10;
265 }
266 else if (var13.stackSize <= var7.getSlotStackLimit())
267 {
268 var7.putStack(var13);
269 var6.setItemStack(var8);
270 }
271 }
272 else if (var8.itemID == var13.itemID && var13.getMaxStackSize() > 1 && (!var8.getHasSubtypes() || var8.getItemDamage() == var13.getItemDamage()) && ItemStack.areItemStackTagsEqual(var8, var13))
273 {
274 var10 = var8.stackSize;
275
276 if (var10 > 0 && var10 + var13.stackSize <= var13.getMaxStackSize())
277 {
278 var13.stackSize += var10;
279 var8 = var7.decrStackSize(var10);
280
281 if (var8.stackSize == 0)
282 {
283 var7.putStack((ItemStack)null);
284 }
285
286 var7.onPickupFromSlot(par4EntityPlayer, var6.getItemStack());
287 }
288 }
289 }
290
291 var7.onSlotChanged();
292 }
293 }
294 }
295 else if (par3 == 2 && par2 >= 0 && par2 < 9)
296 {
297 var7 = (Slot)this.inventorySlots.get(par1);
298
299 if (var7.canTakeStack(par4EntityPlayer))
300 {
301 var8 = var6.getStackInSlot(par2);
302 boolean var9 = var8 == null || var7.inventory == var6 && var7.isItemValid(var8);
303 var10 = -1;
304
305 if (!var9)
306 {
307 var10 = var6.getFirstEmptyStack();
308 var9 |= var10 > -1;
309 }
310
311 if (var7.getHasStack() && var9)
312 {
313 var11 = var7.getStack();
314 var6.setInventorySlotContents(par2, var11);
315
316 if ((var7.inventory != var6 || !var7.isItemValid(var8)) && var8 != null)
317 {
318 if (var10 > -1)
319 {
320 var6.addItemStackToInventory(var8);
321 var7.putStack((ItemStack)null);
322 var7.onPickupFromSlot(par4EntityPlayer, var11);
323 }
324 }
325 else
326 {
327 var7.putStack(var8);
328 var7.onPickupFromSlot(par4EntityPlayer, var11);
329 }
330 }
331 else if (!var7.getHasStack() && var8 != null && var7.isItemValid(var8))
332 {
333 var6.setInventorySlotContents(par2, (ItemStack)null);
334 var7.putStack(var8);
335 }
336 }
337 }
338 else if (par3 == 3 && par4EntityPlayer.capabilities.isCreativeMode && var6.getItemStack() == null && par1 >= 0)
339 {
340 var7 = (Slot)this.inventorySlots.get(par1);
341
342 if (var7 != null && var7.getHasStack())
343 {
344 var8 = var7.getStack().copy();
345 var8.stackSize = var8.getMaxStackSize();
346 var6.setItemStack(var8);
347 }
348 }
349
350 return var5;
351 }
352
353 protected void retrySlotClick(int par1, int par2, boolean par3, EntityPlayer par4EntityPlayer)
354 {
355 this.slotClick(par1, par2, 1, par4EntityPlayer);
356 }
357
358 /**
359 * Callback for when the crafting gui is closed.
360 */
361 public void onCraftGuiClosed(EntityPlayer par1EntityPlayer)
362 {
363 InventoryPlayer var2 = par1EntityPlayer.inventory;
364
365 if (var2.getItemStack() != null)
366 {
367 par1EntityPlayer.dropPlayerItem(var2.getItemStack());
368 var2.setItemStack((ItemStack)null);
369 }
370 }
371
372 /**
373 * Callback for when the crafting matrix is changed.
374 */
375 public void onCraftMatrixChanged(IInventory par1IInventory)
376 {
377 this.updateCraftingResults();
378 }
379
380 /**
381 * args: slotID, itemStack to put in slot
382 */
383 public void putStackInSlot(int par1, ItemStack par2ItemStack)
384 {
385 this.getSlot(par1).putStack(par2ItemStack);
386 }
387
388 @SideOnly(Side.CLIENT)
389
390 /**
391 * places itemstacks in first x slots, x being aitemstack.lenght
392 */
393 public void putStacksInSlots(ItemStack[] par1ArrayOfItemStack)
394 {
395 for (int var2 = 0; var2 < par1ArrayOfItemStack.length; ++var2)
396 {
397 this.getSlot(var2).putStack(par1ArrayOfItemStack[var2]);
398 }
399 }
400
401 @SideOnly(Side.CLIENT)
402 public void updateProgressBar(int par1, int par2) {}
403
404 @SideOnly(Side.CLIENT)
405
406 /**
407 * Gets a unique transaction ID. Parameter is unused.
408 */
409 public short getNextTransactionID(InventoryPlayer par1InventoryPlayer)
410 {
411 ++this.transactionID;
412 return this.transactionID;
413 }
414
415 /**
416 * NotUsing because adding a player twice is an error
417 */
418 public boolean isPlayerNotUsingContainer(EntityPlayer par1EntityPlayer)
419 {
420 return !this.playerList.contains(par1EntityPlayer);
421 }
422
423 /**
424 * adds or removes the player from the container based on par2
425 */
426 public void setPlayerIsPresent(EntityPlayer par1EntityPlayer, boolean par2)
427 {
428 if (par2)
429 {
430 this.playerList.remove(par1EntityPlayer);
431 }
432 else
433 {
434 this.playerList.add(par1EntityPlayer);
435 }
436 }
437
438 public abstract boolean canInteractWith(EntityPlayer var1);
439
440 /**
441 * merges provided ItemStack with the first avaliable one in the container/player inventory
442 */
443 protected boolean mergeItemStack(ItemStack par1ItemStack, int par2, int par3, boolean par4)
444 {
445 boolean var5 = false;
446 int var6 = par2;
447
448 if (par4)
449 {
450 var6 = par3 - 1;
451 }
452
453 Slot var7;
454 ItemStack var8;
455
456 if (par1ItemStack.isStackable())
457 {
458 while (par1ItemStack.stackSize > 0 && (!par4 && var6 < par3 || par4 && var6 >= par2))
459 {
460 var7 = (Slot)this.inventorySlots.get(var6);
461 var8 = var7.getStack();
462
463 if (var8 != null && var8.itemID == par1ItemStack.itemID && (!par1ItemStack.getHasSubtypes() || par1ItemStack.getItemDamage() == var8.getItemDamage()) && ItemStack.areItemStackTagsEqual(par1ItemStack, var8))
464 {
465 int var9 = var8.stackSize + par1ItemStack.stackSize;
466
467 if (var9 <= par1ItemStack.getMaxStackSize())
468 {
469 par1ItemStack.stackSize = 0;
470 var8.stackSize = var9;
471 var7.onSlotChanged();
472 var5 = true;
473 }
474 else if (var8.stackSize < par1ItemStack.getMaxStackSize())
475 {
476 par1ItemStack.stackSize -= par1ItemStack.getMaxStackSize() - var8.stackSize;
477 var8.stackSize = par1ItemStack.getMaxStackSize();
478 var7.onSlotChanged();
479 var5 = true;
480 }
481 }
482
483 if (par4)
484 {
485 --var6;
486 }
487 else
488 {
489 ++var6;
490 }
491 }
492 }
493
494 if (par1ItemStack.stackSize > 0)
495 {
496 if (par4)
497 {
498 var6 = par3 - 1;
499 }
500 else
501 {
502 var6 = par2;
503 }
504
505 while (!par4 && var6 < par3 || par4 && var6 >= par2)
506 {
507 var7 = (Slot)this.inventorySlots.get(var6);
508 var8 = var7.getStack();
509
510 if (var8 == null)
511 {
512 var7.putStack(par1ItemStack.copy());
513 var7.onSlotChanged();
514 par1ItemStack.stackSize = 0;
515 var5 = true;
516 break;
517 }
518
519 if (par4)
520 {
521 --var6;
522 }
523 else
524 {
525 ++var6;
526 }
527 }
528 }
529
530 return var5;
531 }
532 }