    001    package net.minecraft.src;
    002
    003    import cpw.mods.fml.common.Side;
    004    import cpw.mods.fml.common.asm.SideOnly;
    005
    006    public class InventoryPlayer implements IInventory
    007    {
    008        /**
    009         * An array of 36 item stacks indicating the main player inventory (including the visible bar).
    010         */
    011        public ItemStack[] mainInventory = new ItemStack[36];
    012
    013        /** An array of 4 item stacks containing the currently worn armor pieces. */
    014        public ItemStack[] armorInventory = new ItemStack[4];
    015
    016        /** The index of the currently held item (0-8). */
    017        public int currentItem = 0;
    018        @SideOnly(Side.CLIENT)
    019
    020        /** The current ItemStack. */
    021        private ItemStack currentItemStack;
    022
    023        /** The player whose inventory this is. */
    024        public EntityPlayer player;
    025        private ItemStack itemStack;
    026
    027        /**
    028         * Set true whenever the inventory changes. Nothing sets it false so you will have to write your own code to check
    029         * it and reset the value.
    030         */
    031        public boolean inventoryChanged = false;
    032
    033        public InventoryPlayer(EntityPlayer par1EntityPlayer)
    034        {
    035            this.player = par1EntityPlayer;
    036        }
    037
    038        /**
    039         * Returns the item stack currently held by the player.
    040         */
    041        public ItemStack getCurrentItem()
    042        {
    043            return this.currentItem < 9 && this.currentItem >= 0 ? this.mainInventory[this.currentItem] : null;
    044        }
    045
    046        public static int func_70451_h()
    047        {
    048            return 9;
    049        }
    050
    051        /**
    052         * Returns a slot index in main inventory containing a specific itemID
    053         */
    054        private int getInventorySlotContainItem(int par1)
    055        {
    056            for (int var2 = 0; var2 < this.mainInventory.length; ++var2)
    057            {
    058                if (this.mainInventory[var2] != null && this.mainInventory[var2].itemID == par1)
    059                {
    060                    return var2;
    061                }
    062            }
    063
    064            return -1;
    065        }
    066
    067        @SideOnly(Side.CLIENT)
    068        private int getInventorySlotContainItemAndDamage(int par1, int par2)
    069        {
    070            for (int var3 = 0; var3 < this.mainInventory.length; ++var3)
    071            {
    072                if (this.mainInventory[var3] != null && this.mainInventory[var3].itemID == par1 && this.mainInventory[var3].getItemDamage() == par2)
    073                {
    074                    return var3;
    075                }
    076            }
    077
    078            return -1;
    079        }
    080
    081        /**
    082         * stores an itemstack in the users inventory
    083         */
    084        private int storeItemStack(ItemStack par1ItemStack)
    085        {
    086            for (int var2 = 0; var2 < this.mainInventory.length; ++var2)
    087            {
    088                if (this.mainInventory[var2] != null && this.mainInventory[var2].itemID == par1ItemStack.itemID && this.mainInventory[var2].isStackable() && this.mainInventory[var2].stackSize < this.mainInventory[var2].getMaxStackSize() && this.mainInventory[var2].stackSize < this.getInventoryStackLimit() && (!this.mainInventory[var2].getHasSubtypes() || this.mainInventory[var2].getItemDamage() == par1ItemStack.getItemDamage()) && ItemStack.areItemStackTagsEqual(this.mainInventory[var2], par1ItemStack))
    089                {
    090                    return var2;
    091                }
    092            }
    093
    094            return -1;
    095        }
    096
    097        /**
    098         * Returns the first item stack that is empty.
    099         */
    100        public int getFirstEmptyStack()
    101        {
    102            for (int var1 = 0; var1 < this.mainInventory.length; ++var1)
    103            {
    104                if (this.mainInventory[var1] == null)
    105                {
    106                    return var1;
    107                }
    108            }
    109
    110            return -1;
    111        }
    112
    113        @SideOnly(Side.CLIENT)
    114
    115        /**
    116         * Sets a specific itemID as the current item being held (only if it exists on the hotbar)
    117         */
    118        public void setCurrentItem(int par1, int par2, boolean par3, boolean par4)
    119        {
    120            boolean var5 = true;
    121            this.currentItemStack = this.getCurrentItem();
    122            int var7;
    123
    124            if (par3)
    125            {
    126                var7 = this.getInventorySlotContainItemAndDamage(par1, par2);
    127            }
    128            else
    129            {
    130                var7 = this.getInventorySlotContainItem(par1);
    131            }
    132
    133            if (var7 >= 0 && var7 < 9)
    134            {
    135                this.currentItem = var7;
    136            }
    137            else
    138            {
    139                if (par4 && par1 > 0)
    140                {
    141                    int var6 = this.getFirstEmptyStack();
    142
    143                    if (var6 >= 0 && var6 < 9)
    144                    {
    145                        this.currentItem = var6;
    146                    }
    147
    148                    this.func_70439_a(Item.itemsList[par1], par2);
    149                }
    150            }
    151        }
    152
    153        @SideOnly(Side.CLIENT)
    154
    155        /**
    156         * Switch the current item to the next one or the previous one
    157         */
    158        public void changeCurrentItem(int par1)
    159        {
    160            if (par1 > 0)
    161            {
    162                par1 = 1;
    163            }
    164
    165            if (par1 < 0)
    166            {
    167                par1 = -1;
    168            }
    169
    170            for (this.currentItem -= par1; this.currentItem < 0; this.currentItem += 9)
    171            {
    172                ;
    173            }
    174
    175            while (this.currentItem >= 9)
    176            {
    177                this.currentItem -= 9;
    178            }
    179        }
    180
    181        /**
    182         * Clear this player's inventory, using the specified ID and metadata as filters or -1 for no filter.
    183         */
    184        public int clearInventory(int par1, int par2)
    185        {
    186            int var3 = 0;
    187            int var4;
    188            ItemStack var5;
    189
    190            for (var4 = 0; var4 < this.mainInventory.length; ++var4)
    191            {
    192                var5 = this.mainInventory[var4];
    193
    194                if (var5 != null && (par1 <= -1 || var5.itemID == par1) && (par2 <= -1 || var5.getItemDamage() == par2))
    195                {
    196                    var3 += var5.stackSize;
    197                    this.mainInventory[var4] = null;
    198                }
    199            }
    200
    201            for (var4 = 0; var4 < this.armorInventory.length; ++var4)
    202            {
    203                var5 = this.armorInventory[var4];
    204
    205                if (var5 != null && (par1 <= -1 || var5.itemID == par1) && (par2 <= -1 || var5.getItemDamage() == par2))
    206                {
    207                    var3 += var5.stackSize;
    208                    this.armorInventory[var4] = null;
    209                }
    210            }
    211
    212            return var3;
    213        }
    214
    215        @SideOnly(Side.CLIENT)
    216        public void func_70439_a(Item par1Item, int par2)
    217        {
    218            if (par1Item != null)
    219            {
    220                int var3 = this.getInventorySlotContainItemAndDamage(par1Item.shiftedIndex, par2);
    221
    222                if (var3 >= 0)
    223                {
    224                    this.mainInventory[var3] = this.mainInventory[this.currentItem];
    225                }
    226
    227                if (this.currentItemStack != null && this.currentItemStack.isItemEnchantable() && this.getInventorySlotContainItemAndDamage(this.currentItemStack.itemID, this.currentItemStack.getItemDamageForDisplay()) == this.currentItem)
    228                {
    229                    return;
    230                }
    231
    232                this.mainInventory[this.currentItem] = new ItemStack(Item.itemsList[par1Item.shiftedIndex], 1, par2);
    233            }
    234        }
    235
    236        /**
    237         * This function stores as many items of an ItemStack as possible in a matching slot and returns the quantity of
    238         * left over items.
    239         */
    240        private int storePartialItemStack(ItemStack par1ItemStack)
    241        {
    242            int var2 = par1ItemStack.itemID;
    243            int var3 = par1ItemStack.stackSize;
    244            int var4;
    245
    246            if (par1ItemStack.getMaxStackSize() == 1)
    247            {
    248                var4 = this.getFirstEmptyStack();
    249
    250                if (var4 < 0)
    251                {
    252                    return var3;
    253                }
    254                else
    255                {
    256                    if (this.mainInventory[var4] == null)
    257                    {
    258                        this.mainInventory[var4] = ItemStack.copyItemStack(par1ItemStack);
    259                    }
    260
    261                    return 0;
    262                }
    263            }
    264            else
    265            {
    266                var4 = this.storeItemStack(par1ItemStack);
    267
    268                if (var4 < 0)
    269                {
    270                    var4 = this.getFirstEmptyStack();
    271                }
    272
    273                if (var4 < 0)
    274                {
    275                    return var3;
    276                }
    277                else
    278                {
    279                    if (this.mainInventory[var4] == null)
    280                    {
    281                        this.mainInventory[var4] = new ItemStack(var2, 0, par1ItemStack.getItemDamage());
    282
    283                        if (par1ItemStack.hasTagCompound())
    284                        {
    285                            this.mainInventory[var4].setTagCompound((NBTTagCompound)par1ItemStack.getTagCompound().copy());
    286                        }
    287                    }
    288
    289                    int var5 = var3;
    290
    291                    if (var3 > this.mainInventory[var4].getMaxStackSize() - this.mainInventory[var4].stackSize)
    292                    {
    293                        var5 = this.mainInventory[var4].getMaxStackSize() - this.mainInventory[var4].stackSize;
    294                    }
    295
    296                    if (var5 > this.getInventoryStackLimit() - this.mainInventory[var4].stackSize)
    297                    {
    298                        var5 = this.getInventoryStackLimit() - this.mainInventory[var4].stackSize;
    299                    }
    300
    301                    if (var5 == 0)
    302                    {
    303                        return var3;
    304                    }
    305                    else
    306                    {
    307                        var3 -= var5;
    308                        this.mainInventory[var4].stackSize += var5;
    309                        this.mainInventory[var4].animationsToGo = 5;
    310                        return var3;
    311                    }
    312                }
    313            }
    314        }
    315
    316        /**
    317         * Decrement the number of animations remaining. Only called on client side. This is used to handle the animation of
    318         * receiving a block.
    319         */
    320        public void decrementAnimations()
    321        {
    322            for (int var1 = 0; var1 < this.mainInventory.length; ++var1)
    323            {
    324                if (this.mainInventory[var1] != null)
    325                {
    326                    this.mainInventory[var1].updateAnimation(this.player.worldObj, this.player, var1, this.currentItem == var1);
    327                }
    328            }
    329        }
    330
    331        /**
    332         * removed one item of specified itemID from inventory (if it is in a stack, the stack size will reduce with 1)
    333         */
    334        public boolean consumeInventoryItem(int par1)
    335        {
    336            int var2 = this.getInventorySlotContainItem(par1);
    337
    338            if (var2 < 0)
    339            {
    340                return false;
    341            }
    342            else
    343            {
    344                if (--this.mainInventory[var2].stackSize <= 0)
    345                {
    346                    this.mainInventory[var2] = null;
    347                }
    348
    349                return true;
    350            }
    351        }
    352
    353        /**
    354         * Get if a specifiied item id is inside the inventory.
    355         */
    356        public boolean hasItem(int par1)
    357        {
    358            int var2 = this.getInventorySlotContainItem(par1);
    359            return var2 >= 0;
    360        }
    361
    362        /**
    363         * Adds the item stack to the inventory, returns false if it is impossible.
    364         */
    365        public boolean addItemStackToInventory(ItemStack par1ItemStack)
    366        {
    367            int var2;
    368
    369            if (par1ItemStack.isItemDamaged())
    370            {
    371                var2 = this.getFirstEmptyStack();
    372
    373                if (var2 >= 0)
    374                {
    375                    this.mainInventory[var2] = ItemStack.copyItemStack(par1ItemStack);
    376                    this.mainInventory[var2].animationsToGo = 5;
    377                    par1ItemStack.stackSize = 0;
    378                    return true;
    379                }
    380                else if (this.player.capabilities.isCreativeMode)
    381                {
    382                    par1ItemStack.stackSize = 0;
    383                    return true;
    384                }
    385                else
    386                {
    387                    return false;
    388                }
    389            }
    390            else
    391            {
    392                do
    393                {
    394                    var2 = par1ItemStack.stackSize;
    395                    par1ItemStack.stackSize = this.storePartialItemStack(par1ItemStack);
    396                }
    397                while (par1ItemStack.stackSize > 0 && par1ItemStack.stackSize < var2);
    398
    399                if (par1ItemStack.stackSize == var2 && this.player.capabilities.isCreativeMode)
    400                {
    401                    par1ItemStack.stackSize = 0;
    402                    return true;
    403                }
    404                else
    405                {
    406                    return par1ItemStack.stackSize < var2;
    407                }
    408            }
    409        }
    410
    411        /**
    412         * Removes from an inventory slot (first arg) up to a specified number (second arg) of items and returns them in a
    413         * new stack.
    414         */
    415        public ItemStack decrStackSize(int par1, int par2)
    416        {
    417            ItemStack[] var3 = this.mainInventory;
    418
    419            if (par1 >= this.mainInventory.length)
    420            {
    421                var3 = this.armorInventory;
    422                par1 -= this.mainInventory.length;
    423            }
    424
    425            if (var3[par1] != null)
    426            {
    427                ItemStack var4;
    428
    429                if (var3[par1].stackSize <= par2)
    430                {
    431                    var4 = var3[par1];
    432                    var3[par1] = null;
    433                    return var4;
    434                }
    435                else
    436                {
    437                    var4 = var3[par1].splitStack(par2);
    438
    439                    if (var3[par1].stackSize == 0)
    440                    {
    441                        var3[par1] = null;
    442                    }
    443
    444                    return var4;
    445                }
    446            }
    447            else
    448            {
    449                return null;
    450            }
    451        }
    452
    453        /**
    454         * When some containers are closed they call this on each slot, then drop whatever it returns as an EntityItem -
    455         * like when you close a workbench GUI.
    456         */
    457        public ItemStack getStackInSlotOnClosing(int par1)
    458        {
    459            ItemStack[] var2 = this.mainInventory;
    460
    461            if (par1 >= this.mainInventory.length)
    462            {
    463                var2 = this.armorInventory;
    464                par1 -= this.mainInventory.length;
    465            }
    466
    467            if (var2[par1] != null)
    468            {
    469                ItemStack var3 = var2[par1];
    470                var2[par1] = null;
    471                return var3;
    472            }
    473            else
    474            {
    475                return null;
    476            }
    477        }
    478
    479        /**
    480         * Sets the given item stack to the specified slot in the inventory (can be crafting or armor sections).
    481         */
    482        public void setInventorySlotContents(int par1, ItemStack par2ItemStack)
    483        {
    484            ItemStack[] var3 = this.mainInventory;
    485
    486            if (par1 >= var3.length)
    487            {
    488                par1 -= var3.length;
    489                var3 = this.armorInventory;
    490            }
    491
    492            var3[par1] = par2ItemStack;
    493        }
    494
    495        /**
    496         * Gets the strength of the current item (tool) against the specified block, 1.0f if not holding anything.
    497         */
    498        public float getStrVsBlock(Block par1Block)
    499        {
    500            float var2 = 1.0F;
    501
    502            if (this.mainInventory[this.currentItem] != null)
    503            {
    504                var2 *= this.mainInventory[this.currentItem].getStrVsBlock(par1Block);
    505            }
    506
    507            return var2;
    508        }
    509
    510        /**
    511         * Writes the inventory out as a list of compound tags. This is where the slot indices are used (+100 for armor, +80
    512         * for crafting).
    513         */
    514        public NBTTagList writeToNBT(NBTTagList par1NBTTagList)
    515        {
    516            int var2;
    517            NBTTagCompound var3;
    518
    519            for (var2 = 0; var2 < this.mainInventory.length; ++var2)
    520            {
    521                if (this.mainInventory[var2] != null)
    522                {
    523                    var3 = new NBTTagCompound();
    524                    var3.setByte("Slot", (byte)var2);
    525                    this.mainInventory[var2].writeToNBT(var3);
    526                    par1NBTTagList.appendTag(var3);
    527                }
    528            }
    529
    530            for (var2 = 0; var2 < this.armorInventory.length; ++var2)
    531            {
    532                if (this.armorInventory[var2] != null)
    533                {
    534                    var3 = new NBTTagCompound();
    535                    var3.setByte("Slot", (byte)(var2 + 100));
    536                    this.armorInventory[var2].writeToNBT(var3);
    537                    par1NBTTagList.appendTag(var3);
    538                }
    539            }
    540
    541            return par1NBTTagList;
    542        }
    543
    544        /**
    545         * Reads from the given tag list and fills the slots in the inventory with the correct items.
    546         */
    547        public void readFromNBT(NBTTagList par1NBTTagList)
    548        {
    549            this.mainInventory = new ItemStack[36];
    550            this.armorInventory = new ItemStack[4];
    551
    552            for (int var2 = 0; var2 < par1NBTTagList.tagCount(); ++var2)
    553            {
    554                NBTTagCompound var3 = (NBTTagCompound)par1NBTTagList.tagAt(var2);
    555                int var4 = var3.getByte("Slot") & 255;
    556                ItemStack var5 = ItemStack.loadItemStackFromNBT(var3);
    557
    558                if (var5 != null)
    559                {
    560                    if (var4 >= 0 && var4 < this.mainInventory.length)
    561                    {
    562                        this.mainInventory[var4] = var5;
    563                    }
    564
    565                    if (var4 >= 100 && var4 < this.armorInventory.length + 100)
    566                    {
    567                        this.armorInventory[var4 - 100] = var5;
    568                    }
    569                }
    570            }
    571        }
    572
    573        /**
    574         * Returns the number of slots in the inventory.
    575         */
    576        public int getSizeInventory()
    577        {
    578            return this.mainInventory.length + 4;
    579        }
    580
    581        /**
    582         * Returns the stack in slot i
    583         */
    584        public ItemStack getStackInSlot(int par1)
    585        {
    586            ItemStack[] var2 = this.mainInventory;
    587
    588            if (par1 >= var2.length)
    589            {
    590                par1 -= var2.length;
    591                var2 = this.armorInventory;
    592            }
    593
    594            return var2[par1];
    595        }
    596
    597        /**
    598         * Returns the name of the inventory.
    599         */
    600        public String getInvName()
    601        {
    602            return "container.inventory";
    603        }
    604
    605        /**
    606         * Returns the maximum stack size for a inventory slot. Seems to always be 64, possibly will be extended. *Isn't
    607         * this more of a set than a get?*
    608         */
    609        public int getInventoryStackLimit()
    610        {
    611            return 64;
    612        }
    613
    614        /**
    615         * Return damage vs an entity done by the current held weapon, or 1 if nothing is held
    616         */
    617        public int getDamageVsEntity(Entity par1Entity)
    618        {
    619            ItemStack var2 = this.getStackInSlot(this.currentItem);
    620            return var2 != null ? var2.getDamageVsEntity(par1Entity) : 1;
    621        }
    622
    623        /**
    624         * Returns whether the current item (tool) can harvest from the specified block (actually get a result).
    625         */
    626        public boolean canHarvestBlock(Block par1Block)
    627        {
    628            if (par1Block.blockMaterial.isHarvestable())
    629            {
    630                return true;
    631            }
    632            else
    633            {
    634                ItemStack var2 = this.getStackInSlot(this.currentItem);
    635                return var2 != null ? var2.canHarvestBlock(par1Block) : false;
    636            }
    637        }
    638
    639        /**
    640         * returns a player armor item (as itemstack) contained in specified armor slot.
    641         */
    642        public ItemStack armorItemInSlot(int par1)
    643        {
    644            return this.armorInventory[par1];
    645        }
    646
    647        /**
    648         * Based on the damage values and maximum damage values of each armor item, returns the current armor value.
    649         */
    650        public int getTotalArmorValue()
    651        {
    652            int var1 = 0;
    653
    654            for (int var2 = 0; var2 < this.armorInventory.length; ++var2)
    655            {
    656                if (this.armorInventory[var2] != null && this.armorInventory[var2].getItem() instanceof ItemArmor)
    657                {
    658                    int var3 = ((ItemArmor)this.armorInventory[var2].getItem()).damageReduceAmount;
    659                    var1 += var3;
    660                }
    661            }
    662
    663            return var1;
    664        }
    665
    666        /**
    667         * Damages armor in each slot by the specified amount.
    668         */
    669        public void damageArmor(int par1)
    670        {
    671            par1 /= 4;
    672
    673            if (par1 < 1)
    674            {
    675                par1 = 1;
    676            }
    677
    678            for (int var2 = 0; var2 < this.armorInventory.length; ++var2)
    679            {
    680                if (this.armorInventory[var2] != null && this.armorInventory[var2].getItem() instanceof ItemArmor)
    681                {
    682                    this.armorInventory[var2].damageItem(par1, this.player);
    683
    684                    if (this.armorInventory[var2].stackSize == 0)
    685                    {
    686                        this.armorInventory[var2] = null;
    687                    }
    688                }
    689            }
    690        }
    691
    692        /**
    693         * Drop all armor and main inventory items.
    694         */
    695        public void dropAllItems()
    696        {
    697            int var1;
    698
    699            for (var1 = 0; var1 < this.mainInventory.length; ++var1)
    700            {
    701                if (this.mainInventory[var1] != null)
    702                {
    703                    this.player.dropPlayerItemWithRandomChoice(this.mainInventory[var1], true);
    704                    this.mainInventory[var1] = null;
    705                }
    706            }
    707
    708            for (var1 = 0; var1 < this.armorInventory.length; ++var1)
    709            {
    710                if (this.armorInventory[var1] != null)
    711                {
    712                    this.player.dropPlayerItemWithRandomChoice(this.armorInventory[var1], true);
    713                    this.armorInventory[var1] = null;
    714                }
    715            }
    716        }
    717
    718        /**
    719         * Called when an the contents of an Inventory change, usually
    720         */
    721        public void onInventoryChanged()
    722        {
    723            this.inventoryChanged = true;
    724        }
    725
    726        public void setItemStack(ItemStack par1ItemStack)
    727        {
    728            this.itemStack = par1ItemStack;
    729        }
    730
    731        public ItemStack getItemStack()
    732        {
    733            return this.itemStack;
    734        }
    735
    736        /**
    737         * Do not make give this method the name canInteractWith because it clashes with Container
    738         */
    739        public boolean isUseableByPlayer(EntityPlayer par1EntityPlayer)
    740        {
    741            return this.player.isDead ? false : par1EntityPlayer.getDistanceSqToEntity(this.player) <= 64.0D;
    742        }
    743
    744        /**
    745         * Returns true if the specified ItemStack exists in the inventory.
    746         */
    747        public boolean hasItemStack(ItemStack par1ItemStack)
    748        {
    749            int var2;
    750
    751            for (var2 = 0; var2 < this.armorInventory.length; ++var2)
    752            {
    753                if (this.armorInventory[var2] != null && this.armorInventory[var2].isItemEqual(par1ItemStack))
    754                {
    755                    return true;
    756                }
    757            }
    758
    759            for (var2 = 0; var2 < this.mainInventory.length; ++var2)
    760            {
    761                if (this.mainInventory[var2] != null && this.mainInventory[var2].isItemEqual(par1ItemStack))
    762                {
    763                    return true;
    764                }
    765            }
    766
    767            return false;
    768        }
    769
    770        public void openChest() {}
    771
    772        public void closeChest() {}
    773
    774        /**
    775         * Copy the ItemStack contents from another InventoryPlayer instance
    776         */
    777        public void copyInventory(InventoryPlayer par1InventoryPlayer)
    778        {
    779            int var2;
    780
    781            for (var2 = 0; var2 < this.mainInventory.length; ++var2)
    782            {
    783                this.mainInventory[var2] = ItemStack.copyItemStack(par1InventoryPlayer.mainInventory[var2]);
    784            }
    785
    786            for (var2 = 0; var2 < this.armorInventory.length; ++var2)
    787            {
    788                this.armorInventory[var2] = ItemStack.copyItemStack(par1InventoryPlayer.armorInventory[var2]);
    789            }
    790        }
    791    }