mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-06-07 04:17:07 +00:00
BaseInventory: added getMatchingItemCount() helper
this eliminates the performance issues described by #5719. closes #5719 we may want to consider exposing a public API for this in the future, since it might be useful for plugins.
This commit is contained in:
parent
4228880509
commit
eb136e60c8
@ -108,13 +108,23 @@ abstract class BaseInventory implements Inventory{
|
|||||||
$this->onContentChange($oldContents);
|
$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 $checkDamage, bool $checkTags) : int{
|
||||||
|
$item = $this->getItem($slot);
|
||||||
|
return $item->equals($test, $checkDamage, $checkTags) ? $item->getCount() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
public function contains(Item $item) : bool{
|
public function contains(Item $item) : bool{
|
||||||
$count = max(1, $item->getCount());
|
$count = max(1, $item->getCount());
|
||||||
$checkDamage = !$item->hasAnyDamageValue();
|
$checkDamage = !$item->hasAnyDamageValue();
|
||||||
$checkTags = $item->hasNamedTag();
|
$checkTags = $item->hasNamedTag();
|
||||||
foreach($this->getContents() as $i){
|
for($i = 0, $size = $this->getSize(); $i < $size; $i++){
|
||||||
if($item->equals($i, $checkDamage, $checkTags)){
|
$slotCount = $this->getMatchingItemCount($i, $item, $checkDamage, $checkTags);
|
||||||
$count -= $i->getCount();
|
if($slotCount > 0){
|
||||||
|
$count -= $slotCount;
|
||||||
if($count <= 0){
|
if($count <= 0){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -128,9 +138,9 @@ abstract class BaseInventory implements Inventory{
|
|||||||
$slots = [];
|
$slots = [];
|
||||||
$checkDamage = !$item->hasAnyDamageValue();
|
$checkDamage = !$item->hasAnyDamageValue();
|
||||||
$checkTags = $item->hasNamedTag();
|
$checkTags = $item->hasNamedTag();
|
||||||
foreach($this->getContents() as $index => $i){
|
for($i = 0, $size = $this->getSize(); $i < $size; $i++){
|
||||||
if($item->equals($i, $checkDamage, $checkTags)){
|
if($this->getMatchingItemCount($i, $item, $checkDamage, $checkTags) > 0){
|
||||||
$slots[$index] = $i;
|
$slots[$i] = $this->getItem($i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,9 +152,10 @@ abstract class BaseInventory implements Inventory{
|
|||||||
$checkDamage = $exact || !$item->hasAnyDamageValue();
|
$checkDamage = $exact || !$item->hasAnyDamageValue();
|
||||||
$checkTags = $exact || $item->hasNamedTag();
|
$checkTags = $exact || $item->hasNamedTag();
|
||||||
|
|
||||||
foreach($this->getContents() as $index => $i){
|
for($i = 0, $size = $this->getSize(); $i < $size; $i++){
|
||||||
if($item->equals($i, $checkDamage, $checkTags) && ($i->getCount() === $count || (!$exact && $i->getCount() > $count))){
|
$slotCount = $this->getMatchingItemCount($i, $item, $checkDamage, $checkTags);
|
||||||
return $index;
|
if($slotCount > 0 && ($slotCount === $count || (!$exact && $slotCount > $count))){
|
||||||
|
return $i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,11 +188,9 @@ abstract class BaseInventory implements Inventory{
|
|||||||
if($this->isSlotEmpty($i)){
|
if($this->isSlotEmpty($i)){
|
||||||
$count -= $maxStackSize;
|
$count -= $maxStackSize;
|
||||||
}else{
|
}else{
|
||||||
$slot = $this->getItem($i);
|
$slotCount = $this->getMatchingItemCount($i, $item, true, true);
|
||||||
if($item->canStackWith($slot)){
|
if($slotCount > 0 && ($diff = $maxStackSize - $slotCount) > 0){
|
||||||
if(($diff = $maxStackSize - $slot->getCount()) > 0){
|
$count -= $diff;
|
||||||
$count -= $diff;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -226,12 +235,16 @@ abstract class BaseInventory implements Inventory{
|
|||||||
$emptySlots[] = $i;
|
$emptySlots[] = $i;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$slotItem = $this->getItem($i);
|
$slotCount = $this->getMatchingItemCount($i, $newItem, true, true);
|
||||||
|
if($slotCount === 0){
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if($newItem->canStackWith($slotItem) && $slotItem->getCount() < $maxStackSize){
|
if($slotCount < $maxStackSize){
|
||||||
$amount = min($maxStackSize - $slotItem->getCount(), $newItem->getCount());
|
$amount = min($maxStackSize - $slotCount, $newItem->getCount());
|
||||||
if($amount > 0){
|
if($amount > 0){
|
||||||
$newItem->setCount($newItem->getCount() - $amount);
|
$newItem->setCount($newItem->getCount() - $amount);
|
||||||
|
$slotItem = $this->getItem($i);
|
||||||
$slotItem->setCount($slotItem->getCount() + $amount);
|
$slotItem->setCount($slotItem->getCount() + $amount);
|
||||||
$this->setItem($i, $slotItem);
|
$this->setItem($i, $slotItem);
|
||||||
if($newItem->getCount() <= 0){
|
if($newItem->getCount() <= 0){
|
||||||
@ -261,20 +274,20 @@ abstract class BaseInventory implements Inventory{
|
|||||||
$checkDamage = !$item->hasAnyDamageValue();
|
$checkDamage = !$item->hasAnyDamageValue();
|
||||||
$checkTags = $item->hasNamedTag();
|
$checkTags = $item->hasNamedTag();
|
||||||
|
|
||||||
foreach($this->getContents() as $index => $i){
|
for($i = 0, $size = $this->getSize(); $i < $size; $i++){
|
||||||
if($item->equals($i, $checkDamage, $checkTags)){
|
if($this->getMatchingItemCount($i, $item, $checkDamage, $checkTags) > 0){
|
||||||
$this->clear($index);
|
$this->clear($i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function removeItem(Item ...$slots) : array{
|
public function removeItem(Item ...$slots) : array{
|
||||||
/** @var Item[] $itemSlots */
|
/** @var Item[] $searchItems */
|
||||||
/** @var Item[] $slots */
|
/** @var Item[] $slots */
|
||||||
$itemSlots = [];
|
$searchItems = [];
|
||||||
foreach($slots as $slot){
|
foreach($slots as $slot){
|
||||||
if(!$slot->isNull()){
|
if(!$slot->isNull()){
|
||||||
$itemSlots[] = clone $slot;
|
$searchItems[] = clone $slot;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -282,26 +295,28 @@ abstract class BaseInventory implements Inventory{
|
|||||||
if($this->isSlotEmpty($i)){
|
if($this->isSlotEmpty($i)){
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
$item = $this->getItem($i);
|
|
||||||
|
|
||||||
foreach($itemSlots as $index => $slot){
|
foreach($searchItems as $index => $search){
|
||||||
if($slot->equals($item, !$slot->hasAnyDamageValue(), $slot->hasNamedTag())){
|
$slotCount = $this->getMatchingItemCount($i, $search, !$search->hasAnyDamageValue(), $search->hasNamedTag());
|
||||||
$amount = min($item->getCount(), $slot->getCount());
|
if($slotCount > 0){
|
||||||
$slot->setCount($slot->getCount() - $amount);
|
$amount = min($slotCount, $search->getCount());
|
||||||
$item->setCount($item->getCount() - $amount);
|
$search->setCount($search->getCount() - $amount);
|
||||||
$this->setItem($i, $item);
|
|
||||||
if($slot->getCount() <= 0){
|
$slotItem = $this->getItem($i);
|
||||||
unset($itemSlots[$index]);
|
$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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return $itemSlots;
|
return $searchItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function clear(int $index) : void{
|
public function clear(int $index) : void{
|
||||||
|
@ -84,6 +84,11 @@ class SimpleInventory extends BaseInventory{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function getMatchingItemCount(int $slot, Item $test, bool $checkDamage, bool $checkTags) : int{
|
||||||
|
$slotItem = $this->slots[$slot];
|
||||||
|
return $slotItem !== null && $slotItem->equals($test, $checkDamage, $checkTags) ? $slotItem->getCount() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
public function isSlotEmpty(int $index) : bool{
|
public function isSlotEmpty(int $index) : bool{
|
||||||
return $this->slots[$index] === null || $this->slots[$index]->isNull();
|
return $this->slots[$index] === null || $this->slots[$index]->isNull();
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user