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 }