DelegateInventory: use WeakReference and __destruct to clean up inventory listener

this is more sane, since it allows the delegate to be reused without unexpected behaviour.
This commit is contained in:
Dylan K. Taylor 2022-09-30 15:12:37 +01:00
parent 41970feb57
commit 3feaa18f6c
No known key found for this signature in database
GPG Key ID: 8927471A91CAFD3D

View File

@ -24,8 +24,6 @@ declare(strict_types=1);
namespace pocketmine\inventory;
use pocketmine\item\Item;
use pocketmine\player\Player;
use function count;
/**
* An inventory which is backed by another inventory, and acts as a proxy to that inventory.
@ -37,16 +35,25 @@ class DelegateInventory extends BaseInventory{
private Inventory $backingInventory
){
parent::__construct();
$weakThis = \WeakReference::create($this);
$this->backingInventory->getListeners()->add($this->inventoryListener = new CallbackInventoryListener(
function(Inventory $unused, int $slot, Item $oldItem) : void{
$this->onSlotChange($slot, $oldItem);
static function(Inventory $unused, int $slot, Item $oldItem) use ($weakThis) : void{
if(($strongThis = $weakThis->get()) !== null){
$strongThis->onSlotChange($slot, $oldItem);
}
},
function(Inventory $unused, array $oldContents) : void{
$this->onContentChange($oldContents);
static function(Inventory $unused, array $oldContents) use ($weakThis) : void{
if(($strongThis = $weakThis->get()) !== null){
$strongThis->onContentChange($oldContents);
}
}
));
}
public function __destruct(){
$this->backingInventory->getListeners()->remove($this->inventoryListener);
}
public function getSize() : int{
return $this->backingInventory->getSize();
}
@ -66,12 +73,4 @@ class DelegateInventory extends BaseInventory{
protected function internalSetContents(array $items) : void{
$this->backingInventory->setContents($items);
}
public function onClose(Player $who) : void{
parent::onClose($who);
if(count($this->getViewers()) === 0 && count($this->getListeners()->toArray()) === 1){
$this->backingInventory->getListeners()->remove($this->inventoryListener);
$this->inventoryListener = CallbackInventoryListener::onAnyChange(static function() : void{}); //break cyclic reference
}
}
}