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 }