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