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