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