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