    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.func_77970_a(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        public int func_82347_b(int par1, int par2)
    182        {
    183            int var3 = 0;
    184            int var4;
    185            ItemStack var5;
    186
    187            for (var4 = 0; var4 < this.mainInventory.length; ++var4)
    188            {
    189                var5 = this.mainInventory[var4];
    190
    191                if (var5 != null && (par1 <= -1 || var5.itemID == par1) && (par2 <= -1 || var5.getItemDamage() == par2))
    192                {
    193                    var3 += var5.stackSize;
    194                    this.mainInventory[var4] = null;
    195                }
    196            }
    197
    198            for (var4 = 0; var4 < this.armorInventory.length; ++var4)
    199            {
    200                var5 = this.armorInventory[var4];
    201
    202                if (var5 != null && (par1 <= -1 || var5.itemID == par1) && (par2 <= -1 || var5.getItemDamage() == par2))
    203                {
    204                    var3 += var5.stackSize;
    205                    this.armorInventory[var4] = null;
    206                }
    207            }
    208
    209            return var3;
    210        }
    211
    212        @SideOnly(Side.CLIENT)
    213        public void func_70439_a(Item par1Item, int par2)
    214        {
    215            if (par1Item != null)
    216            {
    217                int var3 = this.getInventorySlotContainItemAndDamage(par1Item.shiftedIndex, par2);
    218
    219                if (var3 >= 0)
    220                {
    221                    this.mainInventory[var3] = this.mainInventory[this.currentItem];
    222                }
    223
    224                if (this.currentItemStack != null && this.currentItemStack.isItemEnchantable() && this.getInventorySlotContainItemAndDamage(this.currentItemStack.itemID, this.currentItemStack.getItemDamageForDisplay()) == this.currentItem)
    225                {
    226                    return;
    227                }
    228
    229                this.mainInventory[this.currentItem] = new ItemStack(Item.itemsList[par1Item.shiftedIndex], 1, par2);
    230            }
    231        }
    232
    233        /**
    234         * This function stores as many items of an ItemStack as possible in a matching slot and returns the quantity of
    235         * left over items.
    236         */
    237        private int storePartialItemStack(ItemStack par1ItemStack)
    238        {
    239            int var2 = par1ItemStack.itemID;
    240            int var3 = par1ItemStack.stackSize;
    241            int var4;
    242
    243            if (par1ItemStack.getMaxStackSize() == 1)
    244            {
    245                var4 = this.getFirstEmptyStack();
    246
    247                if (var4 < 0)
    248                {
    249                    return var3;
    250                }
    251                else
    252                {
    253                    if (this.mainInventory[var4] == null)
    254                    {
    255                        this.mainInventory[var4] = ItemStack.copyItemStack(par1ItemStack);
    256                    }
    257
    258                    return 0;
    259                }
    260            }
    261            else
    262            {
    263                var4 = this.storeItemStack(par1ItemStack);
    264
    265                if (var4 < 0)
    266                {
    267                    var4 = this.getFirstEmptyStack();
    268                }
    269
    270                if (var4 < 0)
    271                {
    272                    return var3;
    273                }
    274                else
    275                {
    276                    if (this.mainInventory[var4] == null)
    277                    {
    278                        this.mainInventory[var4] = new ItemStack(var2, 0, par1ItemStack.getItemDamage());
    279
    280                        if (par1ItemStack.hasTagCompound())
    281                        {
    282                            this.mainInventory[var4].setTagCompound((NBTTagCompound)par1ItemStack.getTagCompound().copy());
    283                        }
    284                    }
    285
    286                    int var5 = var3;
    287
    288                    if (var3 > this.mainInventory[var4].getMaxStackSize() - this.mainInventory[var4].stackSize)
    289                    {
    290                        var5 = this.mainInventory[var4].getMaxStackSize() - this.mainInventory[var4].stackSize;
    291                    }
    292
    293                    if (var5 > this.getInventoryStackLimit() - this.mainInventory[var4].stackSize)
    294                    {
    295                        var5 = this.getInventoryStackLimit() - this.mainInventory[var4].stackSize;
    296                    }
    297
    298                    if (var5 == 0)
    299                    {
    300                        return var3;
    301                    }
    302                    else
    303                    {
    304                        var3 -= var5;
    305                        this.mainInventory[var4].stackSize += var5;
    306                        this.mainInventory[var4].animationsToGo = 5;
    307                        return var3;
    308                    }
    309                }
    310            }
    311        }
    312
    313        /**
    314         * Decrement the number of animations remaining. Only called on client side. This is used to handle the animation of
    315         * receiving a block.
    316         */
    317        public void decrementAnimations()
    318        {
    319            for (int var1 = 0; var1 < this.mainInventory.length; ++var1)
    320            {
    321                if (this.mainInventory[var1] != null)
    322                {
    323                    this.mainInventory[var1].updateAnimation(this.player.worldObj, this.player, var1, this.currentItem == var1);
    324                }
    325            }
    326        }
    327
    328        /**
    329         * removed one item of specified itemID from inventory (if it is in a stack, the stack size will reduce with 1)
    330         */
    331        public boolean consumeInventoryItem(int par1)
    332        {
    333            int var2 = this.getInventorySlotContainItem(par1);
    334
    335            if (var2 < 0)
    336            {
    337                return false;
    338            }
    339            else
    340            {
    341                if (--this.mainInventory[var2].stackSize <= 0)
    342                {
    343                    this.mainInventory[var2] = null;
    344                }
    345
    346                return true;
    347            }
    348        }
    349
    350        /**
    351         * Get if a specifiied item id is inside the inventory.
    352         */
    353        public boolean hasItem(int par1)
    354        {
    355            int var2 = this.getInventorySlotContainItem(par1);
    356            return var2 >= 0;
    357        }
    358
    359        /**
    360         * Adds the item stack to the inventory, returns false if it is impossible.
    361         */
    362        public boolean addItemStackToInventory(ItemStack par1ItemStack)
    363        {
    364            int var2;
    365
    366            if (par1ItemStack.isItemDamaged())
    367            {
    368                var2 = this.getFirstEmptyStack();
    369
    370                if (var2 >= 0)
    371                {
    372                    this.mainInventory[var2] = ItemStack.copyItemStack(par1ItemStack);
    373                    this.mainInventory[var2].animationsToGo = 5;
    374                    par1ItemStack.stackSize = 0;
    375                    return true;
    376                }
    377                else if (this.player.capabilities.isCreativeMode)
    378                {
    379                    par1ItemStack.stackSize = 0;
    380                    return true;
    381                }
    382                else
    383                {
    384                    return false;
    385                }
    386            }
    387            else
    388            {
    389                do
    390                {
    391                    var2 = par1ItemStack.stackSize;
    392                    par1ItemStack.stackSize = this.storePartialItemStack(par1ItemStack);
    393                }
    394                while (par1ItemStack.stackSize > 0 && par1ItemStack.stackSize < var2);
    395
    396                if (par1ItemStack.stackSize == var2 && this.player.capabilities.isCreativeMode)
    397                {
    398                    par1ItemStack.stackSize = 0;
    399                    return true;
    400                }
    401                else
    402                {
    403                    return par1ItemStack.stackSize < var2;
    404                }
    405            }
    406        }
    407
    408        /**
    409         * Removes from an inventory slot (first arg) up to a specified number (second arg) of items and returns them in a
    410         * new stack.
    411         */
    412        public ItemStack decrStackSize(int par1, int par2)
    413        {
    414            ItemStack[] var3 = this.mainInventory;
    415
    416            if (par1 >= this.mainInventory.length)
    417            {
    418                var3 = this.armorInventory;
    419                par1 -= this.mainInventory.length;
    420            }
    421
    422            if (var3[par1] != null)
    423            {
    424                ItemStack var4;
    425
    426                if (var3[par1].stackSize <= par2)
    427                {
    428                    var4 = var3[par1];
    429                    var3[par1] = null;
    430                    return var4;
    431                }
    432                else
    433                {
    434                    var4 = var3[par1].splitStack(par2);
    435
    436                    if (var3[par1].stackSize == 0)
    437                    {
    438                        var3[par1] = null;
    439                    }
    440
    441                    return var4;
    442                }
    443            }
    444            else
    445            {
    446                return null;
    447            }
    448        }
    449
    450        /**
    451         * When some containers are closed they call this on each slot, then drop whatever it returns as an EntityItem -
    452         * like when you close a workbench GUI.
    453         */
    454        public ItemStack getStackInSlotOnClosing(int par1)
    455        {
    456            ItemStack[] var2 = this.mainInventory;
    457
    458            if (par1 >= this.mainInventory.length)
    459            {
    460                var2 = this.armorInventory;
    461                par1 -= this.mainInventory.length;
    462            }
    463
    464            if (var2[par1] != null)
    465            {
    466                ItemStack var3 = var2[par1];
    467                var2[par1] = null;
    468                return var3;
    469            }
    470            else
    471            {
    472                return null;
    473            }
    474        }
    475
    476        /**
    477         * Sets the given item stack to the specified slot in the inventory (can be crafting or armor sections).
    478         */
    479        public void setInventorySlotContents(int par1, ItemStack par2ItemStack)
    480        {
    481            ItemStack[] var3 = this.mainInventory;
    482
    483            if (par1 >= var3.length)
    484            {
    485                par1 -= var3.length;
    486                var3 = this.armorInventory;
    487            }
    488
    489            var3[par1] = par2ItemStack;
    490        }
    491
    492        /**
    493         * Gets the strength of the current item (tool) against the specified block, 1.0f if not holding anything.
    494         */
    495        public float getStrVsBlock(Block par1Block)
    496        {
    497            float var2 = 1.0F;
    498
    499            if (this.mainInventory[this.currentItem] != null)
    500            {
    501                var2 *= this.mainInventory[this.currentItem].getStrVsBlock(par1Block);
    502            }
    503
    504            return var2;
    505        }
    506
    507        /**
    508         * Writes the inventory out as a list of compound tags. This is where the slot indices are used (+100 for armor, +80
    509         * for crafting).
    510         */
    511        public NBTTagList writeToNBT(NBTTagList par1NBTTagList)
    512        {
    513            int var2;
    514            NBTTagCompound var3;
    515
    516            for (var2 = 0; var2 < this.mainInventory.length; ++var2)
    517            {
    518                if (this.mainInventory[var2] != null)
    519                {
    520                    var3 = new NBTTagCompound();
    521                    var3.setByte("Slot", (byte)var2);
    522                    this.mainInventory[var2].writeToNBT(var3);
    523                    par1NBTTagList.appendTag(var3);
    524                }
    525            }
    526
    527            for (var2 = 0; var2 < this.armorInventory.length; ++var2)
    528            {
    529                if (this.armorInventory[var2] != null)
    530                {
    531                    var3 = new NBTTagCompound();
    532                    var3.setByte("Slot", (byte)(var2 + 100));
    533                    this.armorInventory[var2].writeToNBT(var3);
    534                    par1NBTTagList.appendTag(var3);
    535                }
    536            }
    537
    538            return par1NBTTagList;
    539        }
    540
    541        /**
    542         * Reads from the given tag list and fills the slots in the inventory with the correct items.
    543         */
    544        public void readFromNBT(NBTTagList par1NBTTagList)
    545        {
    546            this.mainInventory = new ItemStack[36];
    547            this.armorInventory = new ItemStack[4];
    548
    549            for (int var2 = 0; var2 < par1NBTTagList.tagCount(); ++var2)
    550            {
    551                NBTTagCompound var3 = (NBTTagCompound)par1NBTTagList.tagAt(var2);
    552                int var4 = var3.getByte("Slot") & 255;
    553                ItemStack var5 = ItemStack.loadItemStackFromNBT(var3);
    554
    555                if (var5 != null)
    556                {
    557                    if (var4 >= 0 && var4 < this.mainInventory.length)
    558                    {
    559                        this.mainInventory[var4] = var5;
    560                    }
    561
    562                    if (var4 >= 100 && var4 < this.armorInventory.length + 100)
    563                    {
    564                        this.armorInventory[var4 - 100] = var5;
    565                    }
    566                }
    567            }
    568        }
    569
    570        /**
    571         * Returns the number of slots in the inventory.
    572         */
    573        public int getSizeInventory()
    574        {
    575            return this.mainInventory.length + 4;
    576        }
    577
    578        /**
    579         * Returns the stack in slot i
    580         */
    581        public ItemStack getStackInSlot(int par1)
    582        {
    583            ItemStack[] var2 = this.mainInventory;
    584
    585            if (par1 >= var2.length)
    586            {
    587                par1 -= var2.length;
    588                var2 = this.armorInventory;
    589            }
    590
    591            return var2[par1];
    592        }
    593
    594        /**
    595         * Returns the name of the inventory.
    596         */
    597        public String getInvName()
    598        {
    599            return "container.inventory";
    600        }
    601
    602        /**
    603         * Returns the maximum stack size for a inventory slot. Seems to always be 64, possibly will be extended. *Isn't
    604         * this more of a set than a get?*
    605         */
    606        public int getInventoryStackLimit()
    607        {
    608            return 64;
    609        }
    610
    611        /**
    612         * Return damage vs an entity done by the current held weapon, or 1 if nothing is held
    613         */
    614        public int getDamageVsEntity(Entity par1Entity)
    615        {
    616            ItemStack var2 = this.getStackInSlot(this.currentItem);
    617            return var2 != null ? var2.getDamageVsEntity(par1Entity) : 1;
    618        }
    619
    620        /**
    621         * Returns whether the current item (tool) can harvest from the specified block (actually get a result).
    622         */
    623        public boolean canHarvestBlock(Block par1Block)
    624        {
    625            if (par1Block.blockMaterial.isHarvestable())
    626            {
    627                return true;
    628            }
    629            else
    630            {
    631                ItemStack var2 = this.getStackInSlot(this.currentItem);
    632                return var2 != null ? var2.canHarvestBlock(par1Block) : false;
    633            }
    634        }
    635
    636        /**
    637         * returns a player armor item (as itemstack) contained in specified armor slot.
    638         */
    639        public ItemStack armorItemInSlot(int par1)
    640        {
    641            return this.armorInventory[par1];
    642        }
    643
    644        /**
    645         * Based on the damage values and maximum damage values of each armor item, returns the current armor value.
    646         */
    647        public int getTotalArmorValue()
    648        {
    649            int var1 = 0;
    650            ItemStack[] var2 = this.armorInventory;
    651            int var3 = var2.length;
    652
    653            for (int var4 = 0; var4 < var3; ++var4)
    654            {
    655                ItemStack var5 = var2[var4];
    656
    657                if (var5 != null && var5.getItem() instanceof ItemArmor)
    658                {
    659                    int var6 = ((ItemArmor)var5.getItem()).damageReduceAmount;
    660                    var1 += var6;
    661                }
    662            }
    663
    664            return var1;
    665        }
    666
    667        /**
    668         * Damages armor in each slot by the specified amount.
    669         */
    670        public void damageArmor(int par1)
    671        {
    672            par1 /= 4;
    673
    674            if (par1 < 1)
    675            {
    676                par1 = 1;
    677            }
    678
    679            for (int var2 = 0; var2 < this.armorInventory.length; ++var2)
    680            {
    681                if (this.armorInventory[var2] != null && this.armorInventory[var2].getItem() instanceof ItemArmor)
    682                {
    683                    this.armorInventory[var2].damageItem(par1, this.player);
    684
    685                    if (this.armorInventory[var2].stackSize == 0)
    686                    {
    687                        this.armorInventory[var2] = null;
    688                    }
    689                }
    690            }
    691        }
    692
    693        /**
    694         * Drop all armor and main inventory items.
    695         */
    696        public void dropAllItems()
    697        {
    698            int var1;
    699
    700            for (var1 = 0; var1 < this.mainInventory.length; ++var1)
    701            {
    702                if (this.mainInventory[var1] != null)
    703                {
    704                    this.player.dropPlayerItemWithRandomChoice(this.mainInventory[var1], true);
    705                    this.mainInventory[var1] = null;
    706                }
    707            }
    708
    709            for (var1 = 0; var1 < this.armorInventory.length; ++var1)
    710            {
    711                if (this.armorInventory[var1] != null)
    712                {
    713                    this.player.dropPlayerItemWithRandomChoice(this.armorInventory[var1], true);
    714                    this.armorInventory[var1] = null;
    715                }
    716            }
    717        }
    718
    719        /**
    720         * Called when an the contents of an Inventory change, usually
    721         */
    722        public void onInventoryChanged()
    723        {
    724            this.inventoryChanged = true;
    725        }
    726
    727        public void setItemStack(ItemStack par1ItemStack)
    728        {
    729            this.itemStack = par1ItemStack;
    730        }
    731
    732        public ItemStack getItemStack()
    733        {
    734            return this.itemStack;
    735        }
    736
    737        /**
    738         * Do not make give this method the name canInteractWith because it clashes with Container
    739         */
    740        public boolean isUseableByPlayer(EntityPlayer par1EntityPlayer)
    741        {
    742            return this.player.isDead ? false : par1EntityPlayer.getDistanceSqToEntity(this.player) <= 64.0D;
    743        }
    744
    745        /**
    746         * Returns true if the specified ItemStack exists in the inventory.
    747         */
    748        public boolean hasItemStack(ItemStack par1ItemStack)
    749        {
    750            ItemStack[] var2 = this.armorInventory;
    751            int var3 = var2.length;
    752            int var4;
    753            ItemStack var5;
    754
    755            for (var4 = 0; var4 < var3; ++var4)
    756            {
    757                var5 = var2[var4];
    758
    759                if (var5 != null && var5.isItemEqual(par1ItemStack))
    760                {
    761                    return true;
    762                }
    763            }
    764
    765            var2 = this.mainInventory;
    766            var3 = var2.length;
    767
    768            for (var4 = 0; var4 < var3; ++var4)
    769            {
    770                var5 = var2[var4];
    771
    772                if (var5 != null && var5.isItemEqual(par1ItemStack))
    773                {
    774                    return true;
    775                }
    776            }
    777
    778            return false;
    779        }
    780
    781        public void openChest() {}
    782
    783        public void closeChest() {}
    784
    785        /**
    786         * Copy the ItemStack contents from another InventoryPlayer instance
    787         */
    788        public void copyInventory(InventoryPlayer par1InventoryPlayer)
    789        {
    790            int var2;
    791
    792            for (var2 = 0; var2 < this.mainInventory.length; ++var2)
    793            {
    794                this.mainInventory[var2] = ItemStack.copyItemStack(par1InventoryPlayer.mainInventory[var2]);
    795            }
    796
    797            for (var2 = 0; var2 < this.armorInventory.length; ++var2)
    798            {
    799                this.armorInventory[var2] = ItemStack.copyItemStack(par1InventoryPlayer.armorInventory[var2]);
    800            }
    801        }
    802    }