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