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