BaseInventory::addItem(item1,item2,item3) now has the same behaviour as multiple separate addItem() calls (#4237)

fixes #1412
This commit is contained in:
Jason 2021-06-17 16:05:24 -04:00 committed by GitHub
parent 71a4ea2a95
commit 15e5bdb210
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 69 additions and 29 deletions

View File

@ -144,6 +144,20 @@ trait InventoryHelpersTrait{
}
}
/** @var Item[] $returnSlots */
$returnSlots = [];
foreach($itemSlots as $item){
$leftover = $this->internalAddItem($item);
if(!$leftover->isNull()){
$returnSlots[] = $leftover;
}
}
return $returnSlots;
}
private function internalAddItem(Item $slot) : Item{
$emptySlots = [];
for($i = 0, $size = $this->getSize(); $i < $size; ++$i){
@ -152,43 +166,31 @@ trait InventoryHelpersTrait{
$emptySlots[] = $i;
}
foreach($itemSlots as $index => $slot){
if($slot->equals($item) and $item->getCount() < $item->getMaxStackSize()){
$amount = min($item->getMaxStackSize() - $item->getCount(), $slot->getCount(), $this->getMaxStackSize());
if($amount > 0){
$slot->setCount($slot->getCount() - $amount);
$item->setCount($item->getCount() + $amount);
$this->setItem($i, $item);
if($slot->getCount() <= 0){
unset($itemSlots[$index]);
}
if($slot->equals($item) and $item->getCount() < $item->getMaxStackSize()){
$amount = min($item->getMaxStackSize() - $item->getCount(), $slot->getCount(), $this->getMaxStackSize());
if($amount > 0){
$slot->setCount($slot->getCount() - $amount);
$item->setCount($item->getCount() + $amount);
$this->setItem($i, $item);
if($slot->getCount() <= 0){
break;
}
}
}
}
if(count($itemSlots) === 0){
if(count($emptySlots) > 0){
foreach($emptySlots as $slotIndex){
$amount = min($slot->getMaxStackSize(), $slot->getCount(), $this->getMaxStackSize());
$slot->setCount($slot->getCount() - $amount);
$item = clone $slot;
$item->setCount($amount);
$this->setItem($slotIndex, $item);
break;
}
}
if(count($itemSlots) > 0 and count($emptySlots) > 0){
foreach($emptySlots as $slotIndex){
//This loop only gets the first item, then goes to the next empty slot
foreach($itemSlots as $index => $slot){
$amount = min($slot->getMaxStackSize(), $slot->getCount(), $this->getMaxStackSize());
$slot->setCount($slot->getCount() - $amount);
$item = clone $slot;
$item->setCount($amount);
$this->setItem($slotIndex, $item);
if($slot->getCount() <= 0){
unset($itemSlots[$index]);
}
break;
}
}
}
return $itemSlots;
return $slot;
}
public function removeItem(Item ...$slots) : array{

View File

@ -24,8 +24,10 @@ declare(strict_types=1);
namespace pocketmine\inventory;
use PHPUnit\Framework\TestCase;
use pocketmine\item\Item;
use pocketmine\item\ItemFactory;
use pocketmine\item\ItemIds;
use pocketmine\item\VanillaItems;
class BaseInventoryTest extends TestCase{
@ -47,4 +49,40 @@ class BaseInventoryTest extends TestCase{
self::assertFalse($inv->canAddItem($item1), "Item WITH userdata should not stack with item WITHOUT userdata");
self::assertNotEmpty($inv->addItem($item1));
}
/**
* @return Item[]
*/
private function getTestItems() : array{
return [
VanillaItems::APPLE()->setCount(16),
VanillaItems::APPLE()->setCount(16),
VanillaItems::APPLE()->setCount(16),
VanillaItems::APPLE()->setCount(16)
];
}
public function testAddMultipleItemsInOneCall() : void{
$inventory = new class(1) extends SimpleInventory{
};
$leftover = $inventory->addItem(...$this->getTestItems());
self::assertCount(0, $leftover);
self::assertTrue($inventory->getItem(0)->equalsExact(VanillaItems::APPLE()->setCount(64)));
}
public function testAddMultipleItemsInOneCallWithLeftover() : void{
$inventory = new class(1) extends SimpleInventory{};
$inventory->setItem(0, VanillaItems::APPLE()->setCount(20));
$leftover = $inventory->addItem(...$this->getTestItems());
self::assertCount(2, $leftover); //the leftovers are not currently stacked - if they were given separately, they'll be returned separately
self::assertTrue($inventory->getItem(0)->equalsExact(VanillaItems::APPLE()->setCount(64)));
$leftoverCount = 0;
foreach($leftover as $item){
self::assertTrue($item->equals(VanillaItems::APPLE()));
$leftoverCount += $item->getCount();
}
self::assertSame(20, $leftoverCount);
}
}