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