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    }