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