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    }