mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-09 11:16:57 +00:00
Merge branch 'minor-next' into major-next
This commit is contained in:
@ -107,12 +107,22 @@ abstract class BaseInventory implements Inventory{
|
||||
$this->onContentChange($oldContents);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper for utility functions which search the inventory.
|
||||
* TODO: make this abstract instead of providing a slow default implementation (BC break)
|
||||
*/
|
||||
protected function getMatchingItemCount(int $slot, Item $test, bool $checkTags) : int{
|
||||
$item = $this->getItem($slot);
|
||||
return $item->equals($test, true, $checkTags) ? $item->getCount() : 0;
|
||||
}
|
||||
|
||||
public function contains(Item $item) : bool{
|
||||
$count = max(1, $item->getCount());
|
||||
$checkTags = $item->hasNamedTag();
|
||||
foreach($this->getContents() as $i){
|
||||
if($item->equals($i, true, $checkTags)){
|
||||
$count -= $i->getCount();
|
||||
for($i = 0, $size = $this->getSize(); $i < $size; $i++){
|
||||
$slotCount = $this->getMatchingItemCount($i, $item, $checkTags);
|
||||
if($slotCount > 0){
|
||||
$count -= $slotCount;
|
||||
if($count <= 0){
|
||||
return true;
|
||||
}
|
||||
@ -125,9 +135,9 @@ abstract class BaseInventory implements Inventory{
|
||||
public function all(Item $item) : array{
|
||||
$slots = [];
|
||||
$checkTags = $item->hasNamedTag();
|
||||
foreach($this->getContents() as $index => $i){
|
||||
if($item->equals($i, true, $checkTags)){
|
||||
$slots[$index] = $i;
|
||||
for($i = 0, $size = $this->getSize(); $i < $size; $i++){
|
||||
if($this->getMatchingItemCount($i, $item, $checkTags) > 0){
|
||||
$slots[$i] = $this->getItem($i);
|
||||
}
|
||||
}
|
||||
|
||||
@ -138,18 +148,9 @@ abstract class BaseInventory implements Inventory{
|
||||
$count = $exact ? $item->getCount() : max(1, $item->getCount());
|
||||
$checkTags = $exact || $item->hasNamedTag();
|
||||
|
||||
foreach($this->getContents() as $index => $i){
|
||||
if($item->equals($i, true, $checkTags) && ($i->getCount() === $count || (!$exact && $i->getCount() > $count))){
|
||||
return $index;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public function firstEmpty() : int{
|
||||
foreach($this->getContents(true) as $i => $slot){
|
||||
if($slot->isNull()){
|
||||
for($i = 0, $size = $this->getSize(); $i < $size; $i++){
|
||||
$slotCount = $this->getMatchingItemCount($i, $item, $checkTags);
|
||||
if($slotCount > 0 && ($slotCount === $count || (!$exact && $slotCount > $count))){
|
||||
return $i;
|
||||
}
|
||||
}
|
||||
@ -157,6 +158,20 @@ abstract class BaseInventory implements Inventory{
|
||||
return -1;
|
||||
}
|
||||
|
||||
public function firstEmpty() : int{
|
||||
for($i = 0, $size = $this->getSize(); $i < $size; $i++){
|
||||
if($this->isSlotEmpty($i)){
|
||||
return $i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: make this abstract and force implementations to implement it properly (BC break)
|
||||
* This default implementation works, but is slow.
|
||||
*/
|
||||
public function isSlotEmpty(int $index) : bool{
|
||||
return $this->getItem($index)->isNull();
|
||||
}
|
||||
@ -167,14 +182,16 @@ abstract class BaseInventory implements Inventory{
|
||||
|
||||
public function getAddableItemQuantity(Item $item) : int{
|
||||
$count = $item->getCount();
|
||||
$maxStackSize = min($this->getMaxStackSize(), $item->getMaxStackSize());
|
||||
|
||||
for($i = 0, $size = $this->getSize(); $i < $size; ++$i){
|
||||
$slot = $this->getItem($i);
|
||||
if($item->canStackWith($slot)){
|
||||
if(($diff = min($slot->getMaxStackSize(), $item->getMaxStackSize()) - $slot->getCount()) > 0){
|
||||
if($this->isSlotEmpty($i)){
|
||||
$count -= $maxStackSize;
|
||||
}else{
|
||||
$slotCount = $this->getMatchingItemCount($i, $item, true);
|
||||
if($slotCount > 0 && ($diff = $maxStackSize - $slotCount) > 0){
|
||||
$count -= $diff;
|
||||
}
|
||||
}elseif($slot->isNull()){
|
||||
$count -= min($this->getMaxStackSize(), $item->getMaxStackSize());
|
||||
}
|
||||
|
||||
if($count <= 0){
|
||||
@ -208,22 +225,29 @@ abstract class BaseInventory implements Inventory{
|
||||
return $returnSlots;
|
||||
}
|
||||
|
||||
private function internalAddItem(Item $slot) : Item{
|
||||
private function internalAddItem(Item $newItem) : Item{
|
||||
$emptySlots = [];
|
||||
|
||||
$maxStackSize = min($this->getMaxStackSize(), $newItem->getMaxStackSize());
|
||||
|
||||
for($i = 0, $size = $this->getSize(); $i < $size; ++$i){
|
||||
$item = $this->getItem($i);
|
||||
if($item->isNull()){
|
||||
if($this->isSlotEmpty($i)){
|
||||
$emptySlots[] = $i;
|
||||
continue;
|
||||
}
|
||||
$slotCount = $this->getMatchingItemCount($i, $newItem, true);
|
||||
if($slotCount === 0){
|
||||
continue;
|
||||
}
|
||||
|
||||
if($slot->canStackWith($item) && $item->getCount() < $item->getMaxStackSize()){
|
||||
$amount = min($item->getMaxStackSize() - $item->getCount(), $slot->getCount(), $this->getMaxStackSize());
|
||||
if($slotCount < $maxStackSize){
|
||||
$amount = min($maxStackSize - $slotCount, $newItem->getCount());
|
||||
if($amount > 0){
|
||||
$slot->setCount($slot->getCount() - $amount);
|
||||
$item->setCount($item->getCount() + $amount);
|
||||
$this->setItem($i, $item);
|
||||
if($slot->getCount() <= 0){
|
||||
$newItem->setCount($newItem->getCount() - $amount);
|
||||
$slotItem = $this->getItem($i);
|
||||
$slotItem->setCount($slotItem->getCount() + $amount);
|
||||
$this->setItem($i, $slotItem);
|
||||
if($newItem->getCount() <= 0){
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -232,64 +256,66 @@ abstract class BaseInventory implements Inventory{
|
||||
|
||||
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);
|
||||
if($slot->getCount() <= 0){
|
||||
$amount = min($maxStackSize, $newItem->getCount());
|
||||
$newItem->setCount($newItem->getCount() - $amount);
|
||||
$slotItem = clone $newItem;
|
||||
$slotItem->setCount($amount);
|
||||
$this->setItem($slotIndex, $slotItem);
|
||||
if($newItem->getCount() <= 0){
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $slot;
|
||||
return $newItem;
|
||||
}
|
||||
|
||||
public function remove(Item $item) : void{
|
||||
$checkTags = $item->hasNamedTag();
|
||||
|
||||
foreach($this->getContents() as $index => $i){
|
||||
if($item->equals($i, true, $checkTags)){
|
||||
$this->clear($index);
|
||||
for($i = 0, $size = $this->getSize(); $i < $size; $i++){
|
||||
if($this->getMatchingItemCount($i, $item, $checkTags) > 0){
|
||||
$this->clear($i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function removeItem(Item ...$slots) : array{
|
||||
/** @var Item[] $itemSlots */
|
||||
/** @var Item[] $searchItems */
|
||||
/** @var Item[] $slots */
|
||||
$itemSlots = [];
|
||||
$searchItems = [];
|
||||
foreach($slots as $slot){
|
||||
if(!$slot->isNull()){
|
||||
$itemSlots[] = clone $slot;
|
||||
$searchItems[] = clone $slot;
|
||||
}
|
||||
}
|
||||
|
||||
for($i = 0, $size = $this->getSize(); $i < $size; ++$i){
|
||||
$item = $this->getItem($i);
|
||||
if($item->isNull()){
|
||||
if($this->isSlotEmpty($i)){
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach($itemSlots as $index => $slot){
|
||||
if($slot->equals($item, true, $slot->hasNamedTag())){
|
||||
$amount = min($item->getCount(), $slot->getCount());
|
||||
$slot->setCount($slot->getCount() - $amount);
|
||||
$item->setCount($item->getCount() - $amount);
|
||||
$this->setItem($i, $item);
|
||||
if($slot->getCount() <= 0){
|
||||
unset($itemSlots[$index]);
|
||||
foreach($searchItems as $index => $search){
|
||||
$slotCount = $this->getMatchingItemCount($i, $search, $search->hasNamedTag());
|
||||
if($slotCount > 0){
|
||||
$amount = min($slotCount, $search->getCount());
|
||||
$search->setCount($search->getCount() - $amount);
|
||||
|
||||
$slotItem = $this->getItem($i);
|
||||
$slotItem->setCount($slotItem->getCount() - $amount);
|
||||
$this->setItem($i, $slotItem);
|
||||
if($search->getCount() <= 0){
|
||||
unset($searchItems[$index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(count($itemSlots) === 0){
|
||||
if(count($searchItems) === 0){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $itemSlots;
|
||||
return $searchItems;
|
||||
}
|
||||
|
||||
public function clear(int $index) : void{
|
||||
|
@ -85,6 +85,10 @@ class DelegateInventory extends BaseInventory{
|
||||
$this->backingInventory->setContents($items);
|
||||
}
|
||||
|
||||
public function isSlotEmpty(int $index) : bool{
|
||||
return $this->backingInventory->isSlotEmpty($index);
|
||||
}
|
||||
|
||||
protected function onSlotChange(int $index, Item $before) : void{
|
||||
if($this->backingInventoryChanging){
|
||||
parent::onSlotChange($index, $before);
|
||||
|
@ -83,4 +83,13 @@ class SimpleInventory extends BaseInventory{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function getMatchingItemCount(int $slot, Item $test, bool $checkTags) : int{
|
||||
$slotItem = $this->slots[$slot];
|
||||
return $slotItem !== null && $slotItem->equals($test, $checkDamage, $checkTags) ? $slotItem->getCount() : 0;
|
||||
}
|
||||
|
||||
public function isSlotEmpty(int $index) : bool{
|
||||
return $this->slots[$index] === null || $this->slots[$index]->isNull();
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user