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    }