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