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    }