mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-09-05 01:16:15 +00:00
Properly handle transaction building errors instead of kicking the player
This commit is contained in:
@ -29,7 +29,7 @@ use pocketmine\network\mcpe\protocol\types\inventory\ContainerUIIds;
|
||||
use pocketmine\network\mcpe\protocol\types\inventory\stackresponse\ItemStackResponse;
|
||||
use pocketmine\network\mcpe\protocol\types\inventory\stackresponse\ItemStackResponseContainerInfo;
|
||||
use pocketmine\network\mcpe\protocol\types\inventory\stackresponse\ItemStackResponseSlotInfo;
|
||||
use pocketmine\network\PacketHandlingException;
|
||||
use pocketmine\utils\AssumptionFailedError;
|
||||
|
||||
final class ItemStackResponseBuilder{
|
||||
|
||||
@ -51,15 +51,15 @@ final class ItemStackResponseBuilder{
|
||||
/**
|
||||
* @phpstan-return array{Inventory, int}
|
||||
*/
|
||||
private function getInventoryAndSlot(int $containerInterfaceId, int $slotId) : array{
|
||||
private function getInventoryAndSlot(int $containerInterfaceId, int $slotId) : ?array{
|
||||
$windowId = ItemStackContainerIdTranslator::translate($containerInterfaceId, $this->inventoryManager->getCurrentWindowId());
|
||||
$windowAndSlot = $this->inventoryManager->locateWindowAndSlot($windowId, $slotId);
|
||||
if($windowAndSlot === null){
|
||||
throw new PacketHandlingException("Stack request action cannot target an inventory that is not open");
|
||||
return null;
|
||||
}
|
||||
[$inventory, $slot] = $windowAndSlot;
|
||||
if(!$inventory->slotExists($slot)){
|
||||
throw new PacketHandlingException("Stack request action cannot target an inventory slot that does not exist");
|
||||
return null;
|
||||
}
|
||||
|
||||
return [$inventory, $slot];
|
||||
@ -72,16 +72,21 @@ final class ItemStackResponseBuilder{
|
||||
continue;
|
||||
}
|
||||
foreach($slotIds as $slotId){
|
||||
[$inventory, $slot] = $this->getInventoryAndSlot($containerInterfaceId, $slotId);
|
||||
$inventoryAndSlot = $this->getInventoryAndSlot($containerInterfaceId, $slotId);
|
||||
if($inventoryAndSlot === null){
|
||||
//a plugin may have closed the inventory during an event, or the slot may have been invalid
|
||||
continue;
|
||||
}
|
||||
[$inventory, $slot] = $inventoryAndSlot;
|
||||
|
||||
$itemStackInfo = $this->inventoryManager->getItemStackInfo($inventory, $slot);
|
||||
if($itemStackInfo === null){
|
||||
//TODO: what if a plugin closes the inventory while the transaction is ongoing?
|
||||
throw new \LogicException("ItemStackInfo should never be null for an open inventory");
|
||||
throw new AssumptionFailedError("ItemStackInfo should never be null for an open inventory");
|
||||
}
|
||||
if($itemStackInfo->getRequestId() !== $this->requestId){
|
||||
//the itemstack may have been synced due to transaction producing results that the client did not
|
||||
//predict correctly, which will wipe out the tracked request ID (intentionally)
|
||||
//TODO: is this the correct behaviour?
|
||||
continue;
|
||||
}
|
||||
$item = $inventory->getItem($slot);
|
||||
|
Reference in New Issue
Block a user