BaseInventory no longer uses viewers to send updates to players

we want viewers to be as close to decorative as possible, so that they provide useful information to plugins, but don't get in the way of other changes.
This commit is contained in:
Dylan K. Taylor 2024-11-24 17:59:57 +00:00
parent f98cebbd62
commit 473bbe64e0
No known key found for this signature in database
GPG Key ID: 8927471A91CAFD3D
2 changed files with 11 additions and 22 deletions

View File

@ -99,15 +99,10 @@ abstract class BaseInventory implements Inventory, SlotValidatedInventory{
$listeners = $this->listeners->toArray(); $listeners = $this->listeners->toArray();
$this->listeners->clear(); $this->listeners->clear();
$viewers = $this->viewers;
$this->viewers = [];
$this->internalSetContents($items); $this->internalSetContents($items);
$this->listeners->add(...$listeners); //don't directly write, in case listeners were added while operation was in progress $this->listeners->add(...$listeners); //don't directly write, in case listeners were added while operation was in progress
foreach($viewers as $id => $viewer){
$this->viewers[$id] = $viewer;
}
$this->onContentChange($oldContents); $this->onContentChange($oldContents);
} }
@ -369,13 +364,6 @@ abstract class BaseInventory implements Inventory, SlotValidatedInventory{
foreach($this->listeners as $listener){ foreach($this->listeners as $listener){
$listener->onSlotChange($this, $index, $before); $listener->onSlotChange($this, $index, $before);
} }
foreach($this->viewers as $viewer){
$invManager = $viewer->getNetworkSession()->getInvManager();
if($invManager === null){
continue;
}
$invManager->onSlotChange($this, $index);
}
} }
/** /**
@ -386,14 +374,6 @@ abstract class BaseInventory implements Inventory, SlotValidatedInventory{
foreach($this->listeners as $listener){ foreach($this->listeners as $listener){
$listener->onContentChange($this, $itemsBefore); $listener->onContentChange($this, $itemsBefore);
} }
foreach($this->getViewers() as $viewer){
$invManager = $viewer->getNetworkSession()->getInvManager();
if($invManager === null){
continue;
}
$invManager->syncContents($this);
}
} }
public function slotExists(int $slot) : bool{ public function slotExists(int $slot) : bool{

View File

@ -37,10 +37,12 @@ use pocketmine\block\inventory\StonecutterInventory;
use pocketmine\crafting\FurnaceType; use pocketmine\crafting\FurnaceType;
use pocketmine\data\bedrock\EnchantmentIdMap; use pocketmine\data\bedrock\EnchantmentIdMap;
use pocketmine\inventory\Inventory; use pocketmine\inventory\Inventory;
use pocketmine\inventory\InventoryListener;
use pocketmine\inventory\transaction\action\SlotChangeAction; use pocketmine\inventory\transaction\action\SlotChangeAction;
use pocketmine\inventory\transaction\InventoryTransaction; use pocketmine\inventory\transaction\InventoryTransaction;
use pocketmine\item\enchantment\EnchantingOption; use pocketmine\item\enchantment\EnchantingOption;
use pocketmine\item\enchantment\EnchantmentInstance; use pocketmine\item\enchantment\EnchantmentInstance;
use pocketmine\item\Item;
use pocketmine\network\mcpe\cache\CreativeInventoryCache; use pocketmine\network\mcpe\cache\CreativeInventoryCache;
use pocketmine\network\mcpe\protocol\ClientboundPacket; use pocketmine\network\mcpe\protocol\ClientboundPacket;
use pocketmine\network\mcpe\protocol\ContainerClosePacket; use pocketmine\network\mcpe\protocol\ContainerClosePacket;
@ -78,7 +80,7 @@ use function spl_object_id;
/** /**
* @phpstan-type ContainerOpenClosure \Closure(int $id, Inventory $inventory) : (list<ClientboundPacket>|null) * @phpstan-type ContainerOpenClosure \Closure(int $id, Inventory $inventory) : (list<ClientboundPacket>|null)
*/ */
class InventoryManager{ class InventoryManager implements InventoryListener{
/** /**
* @var InventoryManagerEntry[] spl_object_id(Inventory) => InventoryManagerEntry * @var InventoryManagerEntry[] spl_object_id(Inventory) => InventoryManagerEntry
* @phpstan-var array<int, InventoryManagerEntry> * @phpstan-var array<int, InventoryManagerEntry>
@ -149,6 +151,7 @@ class InventoryManager{
throw new \InvalidArgumentException("Inventory " . get_class($inventory) . " is already tracked"); throw new \InvalidArgumentException("Inventory " . get_class($inventory) . " is already tracked");
} }
$this->inventories[spl_object_id($inventory)] = new InventoryManagerEntry($inventory); $this->inventories[spl_object_id($inventory)] = new InventoryManagerEntry($inventory);
$inventory->getListeners()->add($this);
$this->associateIdWithInventory($id, $inventory); $this->associateIdWithInventory($id, $inventory);
} }
@ -171,6 +174,7 @@ class InventoryManager{
$inventory, $inventory,
$complexSlotMap $complexSlotMap
); );
$inventory->getListeners()->add($this);
foreach($complexSlotMap->getSlotMap() as $netSlot => $coreSlot){ foreach($complexSlotMap->getSlotMap() as $netSlot => $coreSlot){
$this->complexSlotToInventoryMap[$netSlot] = $complexSlotMap; $this->complexSlotToInventoryMap[$netSlot] = $complexSlotMap;
} }
@ -191,6 +195,7 @@ class InventoryManager{
$inventory = $this->networkIdToInventoryMap[$id]; $inventory = $this->networkIdToInventoryMap[$id];
unset($this->networkIdToInventoryMap[$id]); unset($this->networkIdToInventoryMap[$id]);
if($this->getWindowId($inventory) === null){ if($this->getWindowId($inventory) === null){
$inventory->getListeners()->remove($this);
unset($this->inventories[spl_object_id($inventory)]); unset($this->inventories[spl_object_id($inventory)]);
foreach($this->complexSlotToInventoryMap as $netSlot => $entry){ foreach($this->complexSlotToInventoryMap as $netSlot => $entry){
if($entry->getInventory() === $inventory){ if($entry->getInventory() === $inventory){
@ -468,7 +473,7 @@ class InventoryManager{
$this->itemStackExtraDataEqual($left, $right); $this->itemStackExtraDataEqual($left, $right);
} }
public function onSlotChange(Inventory $inventory, int $slot) : void{ public function onSlotChange(Inventory $inventory, int $slot, Item $oldItem) : void{
$inventoryEntry = $this->inventories[spl_object_id($inventory)] ?? null; $inventoryEntry = $this->inventories[spl_object_id($inventory)] ?? null;
if($inventoryEntry === null){ if($inventoryEntry === null){
//this can happen when an inventory changed during InventoryCloseEvent, or when a temporary inventory //this can happen when an inventory changed during InventoryCloseEvent, or when a temporary inventory
@ -570,6 +575,10 @@ class InventoryManager{
unset($entry->predictions[$slot], $entry->pendingSyncs[$slot]); unset($entry->predictions[$slot], $entry->pendingSyncs[$slot]);
} }
public function onContentChange(Inventory $inventory, array $oldContents) : void{
$this->syncContents($inventory);
}
public function syncContents(Inventory $inventory) : void{ public function syncContents(Inventory $inventory) : void{
$entry = $this->inventories[spl_object_id($inventory)] ?? null; $entry = $this->inventories[spl_object_id($inventory)] ?? null;
if($entry === null){ if($entry === null){