001    package net.minecraft.entity.player;
002    
003    import cpw.mods.fml.relauncher.Side;
004    import cpw.mods.fml.relauncher.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            this.currentItem = par1InventoryPlayer.currentItem;
800        }
801    }