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