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