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 }