the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at main 784 lines 16 kB view raw
1#include "stdafx.h" 2#include "com.mojang.nbt.h" 3#include "net.minecraft.world.entity.player.h" 4#include "net.minecraft.world.item.h" 5#include "net.minecraft.world.level.tile.h" 6#include "net.minecraft.stats.h" 7#include "Material.h" 8#include "Inventory.h" 9 10const int Inventory::POP_TIME_DURATION = 5; 11const int Inventory::MAX_INVENTORY_STACK_SIZE = 64; 12 13const int Inventory::INVENTORY_SIZE = 4 * 9; 14const int Inventory::SELECTION_SIZE = 9; 15 16// 4J Stu - The Pllayer is managed by shared_ptrs elsewhere, but it owns us so we don't want to also 17// keep a shared_ptr of it. If we pass it on we should use shared_from_this() though 18Inventory::Inventory(Player *player) 19{ 20 items = ItemInstanceArray( INVENTORY_SIZE ); 21 armor = ItemInstanceArray( 4 ); 22 23 selected = 0; 24 25 carried = nullptr; 26 27 changed = false; 28 29 this->player = player; 30} 31 32Inventory::~Inventory() 33{ 34 delete [] items.data; 35 delete [] armor.data; 36} 37 38shared_ptr<ItemInstance> Inventory::getSelected() 39{ 40 // sanity checking to prevent exploits 41 if (selected < SELECTION_SIZE && selected >= 0) 42 { 43 return items[selected]; 44 } 45 return nullptr; 46} 47 48// 4J-PB - Added for the in-game tooltips 49bool Inventory::IsHeldItem() 50{ 51 // sanity checking to prevent exploits 52 if (selected < SELECTION_SIZE && selected >= 0) 53 { 54 if(items[selected]) 55 { 56 return true; 57 } 58 } 59 return false; 60} 61 62int Inventory::getSelectionSize() 63{ 64 return SELECTION_SIZE; 65} 66 67 68int Inventory::getSlot(int tileId) 69{ 70 for (unsigned int i = 0; i < items.length; i++) 71 { 72 if (items[i] != NULL && items[i]->id == tileId) return i; 73 } 74 return -1; 75} 76 77int Inventory::getSlot(int tileId, int data) 78{ 79 for (int i = 0; i < items.length; i++) 80 { 81 if (items[i] != NULL && items[i]->id == tileId && items[i]->getAuxValue() == data) return i; 82 } 83 return -1; 84} 85 86int Inventory::getSlotWithRemainingSpace(shared_ptr<ItemInstance> item) 87{ 88 for (unsigned int i = 0; i < items.length; i++) 89 { 90 if (items[i] != NULL && items[i]->id == item->id && items[i]->isStackable() 91 && items[i]->count < items[i]->getMaxStackSize() && items[i]->count < getMaxStackSize() 92 && (!items[i]->isStackedByData() || items[i]->getAuxValue() == item->getAuxValue()) 93 && ItemInstance::tagMatches(items[i], item)) 94 { 95 return i; 96 } 97 } 98 return -1; 99} 100 101int Inventory::getFreeSlot() 102{ 103 for (unsigned int i = 0; i < items.length; i++) 104 { 105 if (items[i] == NULL) return i; 106 } 107 return -1; 108} 109 110 111void Inventory::grabTexture(int id, int data, bool checkData, bool mayReplace) 112{ 113 int slot = -1; 114 heldItem = getSelected(); 115 if (checkData) 116 { 117 slot = getSlot(id, data); 118 } 119 else 120 { 121 slot = getSlot(id); 122 } 123 if (slot >= 0 && slot < 9) 124 { 125 selected = slot; 126 return; 127 } 128 129 if (mayReplace) 130 { 131 if (id > 0) 132 { 133 int firstEmpty = getFreeSlot(); 134 if (firstEmpty >= 0 && firstEmpty < 9) 135 { 136 selected = firstEmpty; 137 } 138 139 replaceSlot(Item::items[id], data); 140 } 141 } 142} 143 144void Inventory::swapPaint(int wheel) 145{ 146 if (wheel > 0) wheel = 1; 147 if (wheel < 0) wheel = -1; 148 149 selected -= wheel; 150 151 while (selected < 0) 152 selected += 9; 153 while (selected >= 9) 154 selected -= 9; 155} 156 157int Inventory::clearInventory(int id, int data) 158{ 159 int count = 0; 160 for (int i = 0; i < items.length; i++) 161 { 162 shared_ptr<ItemInstance> item = items[i]; 163 if (item == NULL) continue; 164 if (id > -1 && item->id != id) continue; 165 if (data > -1 && item->getAuxValue() != data) continue; 166 167 count += item->count; 168 items[i] = nullptr; 169 } 170 for (int i = 0; i < armor.length; i++) 171 { 172 shared_ptr<ItemInstance> item = armor[i]; 173 if (item == NULL) continue; 174 if (id > -1 && item->id != id) continue; 175 if (data > -1 && item->getAuxValue() != data) continue; 176 177 count += item->count; 178 armor[i] = nullptr; 179 } 180 181 if (carried != NULL) 182 { 183 if (id > -1 && carried->id != id) return count; 184 if (data > -1 && carried->getAuxValue() != data) return count; 185 186 count += carried->count; 187 setCarried(nullptr); 188 } 189 190 return count; 191} 192 193void Inventory::replaceSlot(Item *item, int data) 194{ 195 if (item != NULL) 196 { 197 // It's too easy to accidentally pick block and lose enchanted items. 198 if (heldItem != NULL && heldItem->isEnchantable() && getSlot(heldItem->id, heldItem->getDamageValue()) == selected) 199 { 200 return; 201 } 202 203 int oldSlot = getSlot(item->id, data); 204 if (oldSlot >= 0) 205 { 206 int oldSlotCount = items[oldSlot]->count; 207 items[oldSlot] = items[selected]; 208 items[selected] = shared_ptr<ItemInstance>( new ItemInstance(Item::items[item->id], oldSlotCount, data) ); 209 } 210 else 211 { 212 items[selected] = shared_ptr<ItemInstance>(new ItemInstance(Item::items[item->id], 1, data)); 213 } 214 } 215} 216 217 218int Inventory::addResource(shared_ptr<ItemInstance> itemInstance) 219{ 220 221 int type = itemInstance->id; 222 int count = itemInstance->count; 223 224 // 4J Stu - Brought forward from 1.2 225 if (itemInstance->getMaxStackSize() == 1) 226 { 227 int slot = getFreeSlot(); 228 if (slot < 0) return count; 229 if (items[slot] == NULL) 230 { 231 items[slot] = ItemInstance::clone(itemInstance); 232 player->handleCollectItem(itemInstance); 233 } 234 return 0; 235 } 236 237 int slot = getSlotWithRemainingSpace(itemInstance); 238 if (slot < 0) slot = getFreeSlot(); 239 if (slot < 0) return count; 240 if (items[slot] == NULL) 241 { 242 items[slot] = shared_ptr<ItemInstance>( new ItemInstance(type, 0, itemInstance->getAuxValue()) ); 243 // 4J Stu - Brought forward from 1.2 244 if (itemInstance->hasTag()) 245 { 246 items[slot]->setTag((CompoundTag *) itemInstance->getTag()->copy()); 247 player->handleCollectItem(itemInstance); 248 } 249 } 250 251 int toAdd = count; 252 if (toAdd > items[slot]->getMaxStackSize() - items[slot]->count) 253 { 254 toAdd = items[slot]->getMaxStackSize() - items[slot]->count; 255 } 256 if (toAdd > getMaxStackSize() - items[slot]->count) 257 { 258 toAdd = getMaxStackSize() - items[slot]->count; 259 } 260 261 if (toAdd == 0) return count; 262 263 count -= toAdd; 264 items[slot]->count += toAdd; 265 items[slot]->popTime = POP_TIME_DURATION; 266 267 return count; 268} 269 270 271void Inventory::tick() 272{ 273 for (unsigned int i = 0; i < items.length; i++) 274 { 275 if (items[i] != NULL) 276 { 277 items[i]->inventoryTick(player->level, player->shared_from_this(), i, selected == i); 278 } 279 } 280} 281 282bool Inventory::removeResource(int type) 283{ 284 int slot = getSlot(type); 285 if (slot < 0) return false; 286 if (--items[slot]->count <= 0) items[slot] = nullptr; 287 288 return true; 289} 290 291bool Inventory::removeResource(int type,int iAuxVal) 292{ 293 int slot = getSlot(type,iAuxVal); 294 if (slot < 0) return false; 295 if (--items[slot]->count <= 0) items[slot] = nullptr; 296 297 return true; 298} 299 300void Inventory::removeResources(shared_ptr<ItemInstance> item) 301{ 302 if(item == NULL) return; 303 304 int countToRemove = item->count; 305 for (unsigned int i = 0; i < items.length; i++) 306 { 307 if (items[i] != NULL && items[i]->sameItemWithTags(item)) 308 { 309 int slotCount = items[i]->count; 310 items[i]->count -= countToRemove; 311 if(slotCount < countToRemove) 312 { 313 countToRemove -= slotCount; 314 } 315 else 316 { 317 countToRemove = 0; 318 } 319 if(items[i]->count <= 0) items[i] = nullptr; 320 } 321 } 322} 323 324shared_ptr<ItemInstance> Inventory::getResourceItem(int type) 325{ 326 int slot = getSlot(type); 327 if (slot < 0) return nullptr; 328 return getItem( slot ); 329} 330 331shared_ptr<ItemInstance> Inventory::getResourceItem(int type,int iAuxVal) 332{ 333 int slot = getSlot(type,iAuxVal); 334 if (slot < 0) return nullptr; 335 return getItem( slot ); 336} 337 338bool Inventory::hasResource(int type) 339{ 340 int slot = getSlot(type); 341 if (slot < 0) return false; 342 343 return true; 344} 345 346void Inventory::swapSlots(int from, int to) 347{ 348 shared_ptr<ItemInstance> tmp = items[to]; 349 items[to] = items[from]; 350 items[from] = tmp; 351} 352 353bool Inventory::add(shared_ptr<ItemInstance> item) 354{ 355 if (item == NULL) return false; 356 if (item->count == 0) return false; 357 358 if (!item->isDamaged()) 359 { 360 int lastSize; 361 int count = item->count; 362 do 363 { 364 lastSize = item->count; 365 item->count = addResource(item); 366 } while (item->count > 0 && item->count < lastSize); 367 if (item->count == lastSize && player->abilities.instabuild) 368 { 369 // silently destroy the item when having a full inventory 370 item->count = 0; 371 return true; 372 } 373 if( item->count < lastSize ) 374 { 375 player->awardStat( 376 GenericStats::itemsCollected(item->id, item->getAuxValue()), 377 GenericStats::param_itemsCollected(item->id, item->getAuxValue(), count) 378 ); 379 return true; 380 } 381 else 382 return false; 383 } 384 385 int slot = getFreeSlot(); 386 if (slot >= 0) 387 { 388 player->handleCollectItem(item); 389 390 player->awardStat( 391 GenericStats::itemsCollected(item->id, item->getAuxValue()), 392 GenericStats::param_itemsCollected(item->id, item->getAuxValue(), item->GetCount())); 393 394 items[slot] = ItemInstance::clone(item); 395 items[slot]->popTime = POP_TIME_DURATION; 396 item->count = 0; 397 return true; 398 } 399 else if (player->abilities.instabuild) 400 { 401 // silently destroy the item when having a full inventory 402 item->count = 0; 403 return true; 404 } 405 return false; 406} 407 408shared_ptr<ItemInstance> Inventory::removeItem(unsigned int slot, int count) 409{ 410 411 ItemInstanceArray pile = items; 412 if (slot >= items.length) 413 { 414 pile = armor; 415 slot -= items.length; 416 } 417 418 if (pile[slot] != NULL) 419 { 420 if (pile[slot]->count <= count) 421 { 422 shared_ptr<ItemInstance> item = pile[slot]; 423 pile[slot] = nullptr; 424 return item; 425 } 426 else 427 { 428 shared_ptr<ItemInstance> i = pile[slot]->remove(count); 429 if (pile[slot]->count == 0) pile[slot] = nullptr; 430 return i; 431 } 432 } 433 return nullptr; 434} 435 436shared_ptr<ItemInstance> Inventory::removeItemNoUpdate(int slot) 437{ 438 ItemInstanceArray pile = items; 439 if (slot >= items.length) 440 { 441 pile = armor; 442 slot -= items.length; 443 } 444 445 if (pile[slot] != NULL) 446 { 447 shared_ptr<ItemInstance> item = pile[slot]; 448 pile[slot] = nullptr; 449 return item; 450 } 451 return nullptr; 452} 453 454void Inventory::setItem(unsigned int slot, shared_ptr<ItemInstance> item) 455{ 456#ifdef _DEBUG 457 if(item!=NULL) 458 { 459 wstring itemstring=item->toString(); 460 app.DebugPrintf("Inventory::setItem - slot = %d,\t item = %d ",slot,item->id); 461 //OutputDebugStringW(itemstring.c_str()); 462 app.DebugPrintf("\n"); 463 } 464#else 465 if(item!=NULL) 466 { 467 app.DebugPrintf("Inventory::setItem - slot = %d,\t item = %d, aux = %d\n",slot,item->id,item->getAuxValue()); 468 } 469#endif 470 // 4J Stu - Changed this a little from Java to be less funn 471 if( slot >= items.length ) 472 { 473 armor[slot - items.length] = item; 474 } 475 else 476 { 477 items[slot] = item; 478 } 479 player->handleCollectItem(item); 480 /* 481 ItemInstanceArray& pile = items; 482 if (slot >= pile.length) 483 { 484 slot -= pile.length; 485 pile = armor; 486 } 487 488 pile[slot] = item; 489 */ 490} 491 492float Inventory::getDestroySpeed(Tile *tile) 493{ 494 float speed = 1.0f; 495 if (items[selected] != NULL) speed *= items[selected]->getDestroySpeed(tile); 496 return speed; 497} 498 499ListTag<CompoundTag> *Inventory::save(ListTag<CompoundTag> *listTag) 500{ 501 for (unsigned int i = 0; i < items.length; i++) 502 { 503 if (items[i] != NULL) 504 { 505 CompoundTag *tag = new CompoundTag(); 506 tag->putByte(L"Slot", (byte) i); 507 items[i]->save(tag); 508 listTag->add(tag); 509 } 510 } 511 for (unsigned int i = 0; i < armor.length; i++) 512 { 513 if (armor[i] != NULL) 514 { 515 CompoundTag *tag = new CompoundTag(); 516 tag->putByte(L"Slot", (byte) (i + 100)); 517 armor[i]->save(tag); 518 listTag->add(tag); 519 } 520 } 521 return listTag; 522} 523 524void Inventory::load(ListTag<CompoundTag> *inventoryList) 525{ 526 if( items.data != NULL) 527 { 528 delete[] items.data; 529 items.data = NULL; 530 } 531 if( armor.data != NULL) 532 { 533 delete[] armor.data; 534 armor.data = NULL; 535 536 } 537 items = ItemInstanceArray( INVENTORY_SIZE ); 538 armor = ItemInstanceArray( 4 ); 539 for (int i = 0; i < inventoryList->size(); i++) 540 { 541 CompoundTag *tag = inventoryList->get(i); 542 unsigned int slot = tag->getByte(L"Slot") & 0xff; 543 shared_ptr<ItemInstance> item = shared_ptr<ItemInstance>( ItemInstance::fromTag(tag) ); 544 if (item != NULL) 545 { 546 if (slot >= 0 && slot < items.length) items[slot] = item; 547 if (slot >= 100 && slot < armor.length + 100) armor[slot - 100] = item; 548 } 549 } 550} 551 552unsigned int Inventory::getContainerSize() 553{ 554 return items.length + 4; 555} 556 557shared_ptr<ItemInstance> Inventory::getItem(unsigned int slot) 558{ 559 // 4J Stu - Changed this a little from the Java so it's less funny 560 if( slot >= items.length ) 561 { 562 return armor[ slot - items.length ]; 563 } 564 else 565 { 566 return items[ slot ]; 567 } 568 /* 569 ItemInstanceArray pile = items; 570 if (slot >= pile.length) 571 { 572 slot -= pile.length; 573 pile = armor; 574 } 575 576 return pile[slot]; 577 */ 578} 579 580wstring Inventory::getName() 581{ 582 return app.GetString(IDS_INVENTORY); 583} 584 585wstring Inventory::getCustomName() 586{ 587 return L""; 588} 589 590bool Inventory::hasCustomName() 591{ 592 return false; 593} 594 595int Inventory::getMaxStackSize() const 596{ 597 return MAX_INVENTORY_STACK_SIZE; 598} 599 600bool Inventory::canDestroy(Tile *tile) 601{ 602 if (tile->material->isAlwaysDestroyable()) return true; 603 604 shared_ptr<ItemInstance> item = getItem(selected); 605 if (item != NULL) return item->canDestroySpecial(tile); 606 return false; 607} 608 609shared_ptr<ItemInstance> Inventory::getArmor(int layer) 610{ 611 return armor[layer]; 612} 613 614int Inventory::getArmorValue() 615{ 616 int val = 0; 617 for (unsigned int i = 0; i < armor.length; i++) 618 { 619 if (armor[i] != NULL && dynamic_cast<ArmorItem *>( armor[i]->getItem() ) != NULL ) 620 { 621 int baseProtection = dynamic_cast<ArmorItem *>(armor[i]->getItem())->defense; 622 623 val += baseProtection; 624 } 625 } 626 return val; 627} 628 629void Inventory::hurtArmor(float dmg) 630{ 631 dmg = dmg / 4; 632 if (dmg < 1) 633 { 634 dmg = 1; 635 } 636 for (unsigned int i = 0; i < armor.length; i++) 637 { 638 if (armor[i] != NULL && dynamic_cast<ArmorItem *>( armor[i]->getItem() ) != NULL ) 639 { 640 armor[i]->hurtAndBreak( (int) dmg, dynamic_pointer_cast<LivingEntity>( player->shared_from_this() ) ); 641 if (armor[i]->count == 0) 642 { 643 armor[i] = nullptr; 644 } 645 } 646 } 647} 648 649void Inventory::dropAll() 650{ 651 for (unsigned int i = 0; i < items.length; i++) 652 { 653 if (items[i] != NULL) 654 { 655 player->drop(items[i], true); 656 items[i] = nullptr; 657 } 658 } 659 for (unsigned int i = 0; i < armor.length; i++) 660 { 661 if (armor[i] != NULL) 662 { 663 player->drop(armor[i], true); 664 armor[i] = nullptr; 665 } 666 } 667} 668 669void Inventory::setChanged() 670{ 671 changed = true; 672} 673 674bool Inventory::isSame(shared_ptr<Inventory> copy) 675{ 676 for (unsigned int i = 0; i < items.length; i++) 677 { 678 if (!isSame( copy->items[i], items[i])) return false; 679 } 680 for (unsigned int i = 0; i < armor.length; i++) 681 { 682 if (!isSame( copy->armor[i], armor[i])) return false; 683 } 684 return true; 685} 686 687 688bool Inventory::isSame(shared_ptr<ItemInstance> a, shared_ptr<ItemInstance> b) 689{ 690 if (a == NULL && b == NULL) return true; 691 if (a == NULL || b == NULL) return false; 692 693 return a->id == b->id && a->count == b->count && a->getAuxValue() == b->getAuxValue(); 694} 695 696 697shared_ptr<Inventory> Inventory::copy() 698{ 699 shared_ptr<Inventory> copy = shared_ptr<Inventory>( new Inventory(NULL) ); 700 for (unsigned int i = 0; i < items.length; i++) 701 { 702 copy->items[i] = items[i] != NULL ? items[i]->copy() : nullptr; 703 } 704 for (unsigned int i = 0; i < armor.length; i++) 705 { 706 copy->armor[i] = armor[i] != NULL ? armor[i]->copy() : nullptr; 707 } 708 return copy; 709} 710 711void Inventory::setCarried(shared_ptr<ItemInstance> carried) 712{ 713 this->carried = carried; 714 player->handleCollectItem(carried); 715} 716 717shared_ptr<ItemInstance> Inventory::getCarried() 718{ 719 return carried; 720} 721 722bool Inventory::stillValid(shared_ptr<Player> player) 723{ 724 if (this->player->removed) return false; 725 if (player->distanceToSqr(this->player->shared_from_this()) > 8 * 8) return false; 726 return true; 727} 728 729bool Inventory::contains(shared_ptr<ItemInstance> itemInstance) 730{ 731 for (unsigned int i = 0; i < armor.length; i++) 732 { 733 if (armor[i] != NULL && armor[i]->sameItem(itemInstance)) return true; 734 } 735 for (unsigned int i = 0; i < items.length; i++) 736 { 737 if (items[i] != NULL && items[i]->sameItem(itemInstance)) return true; 738 } 739 return false; 740} 741 742void Inventory::startOpen() 743{ 744 // TODO Auto-generated method stub 745} 746 747void Inventory::stopOpen() 748{ 749 // TODO Auto-generated method stub 750} 751 752bool Inventory::canPlaceItem(int slot, shared_ptr<ItemInstance> item) 753{ 754 return true; 755} 756 757void Inventory::replaceWith(shared_ptr<Inventory> other) 758{ 759 for (int i = 0; i < items.length; i++) 760 { 761 items[i] = ItemInstance::clone(other->items[i]); 762 } 763 for (int i = 0; i < armor.length; i++) 764 { 765 armor[i] = ItemInstance::clone(other->armor[i]); 766 } 767 768 selected = other->selected; 769} 770 771int Inventory::countMatches(shared_ptr<ItemInstance> itemInstance) 772{ 773 if(itemInstance == NULL) return 0; 774 int count = 0; 775 //for (unsigned int i = 0; i < armor.length; i++) 776 //{ 777 // if (armor[i] != NULL && armor[i]->sameItem(itemInstance)) count += items[i]->count; 778 //} 779 for (unsigned int i = 0; i < items.length; i++) 780 { 781 if (items[i] != NULL && items[i]->sameItemWithTags(itemInstance)) count += items[i]->count; 782 } 783 return count; 784}