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