    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    }