From ebcfab4b61367e915ef4619e1e4c7e85420111dd Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Thu, 23 Apr 2020 15:40:23 +0100 Subject: [PATCH] NetworkInventoryAction: move type translation to TypeConverter --- src/network/mcpe/convert/TypeConverter.php | 81 +++++++++++++++++++ .../mcpe/handler/InGamePacketHandler.php | 7 +- .../inventory/NetworkInventoryAction.php | 79 ------------------ 3 files changed, 85 insertions(+), 82 deletions(-) diff --git a/src/network/mcpe/convert/TypeConverter.php b/src/network/mcpe/convert/TypeConverter.php index 775095a56..1a6a79a7e 100644 --- a/src/network/mcpe/convert/TypeConverter.php +++ b/src/network/mcpe/convert/TypeConverter.php @@ -22,14 +22,24 @@ declare(strict_types=1); namespace pocketmine\network\mcpe\convert; +use pocketmine\crafting\CraftingGrid; +use pocketmine\inventory\transaction\action\CreateItemAction; +use pocketmine\inventory\transaction\action\DestroyItemAction; +use pocketmine\inventory\transaction\action\DropItemAction; +use pocketmine\inventory\transaction\action\InventoryAction; +use pocketmine\inventory\transaction\action\SlotChangeAction; use pocketmine\item\Durable; use pocketmine\item\Item; use pocketmine\item\ItemFactory; use pocketmine\item\ItemIds; use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\IntTag; +use pocketmine\network\mcpe\protocol\InventoryTransactionPacket; +use pocketmine\network\mcpe\protocol\types\inventory\ContainerIds; use pocketmine\network\mcpe\protocol\types\inventory\ItemStack; +use pocketmine\network\mcpe\protocol\types\inventory\NetworkInventoryAction; use pocketmine\network\mcpe\protocol\types\recipe\RecipeIngredient; +use pocketmine\player\Player; class TypeConverter{ private const DAMAGE_TAG = "Damage"; //TAG_Int @@ -121,4 +131,75 @@ class TypeConverter{ $compound ); } + + /** + * @throws \UnexpectedValueException + */ + public function createInventoryAction(NetworkInventoryAction $action, Player $player) : ?InventoryAction{ + $old = TypeConverter::getInstance()->netItemStackToCore($action->oldItem); + $new = TypeConverter::getInstance()->netItemStackToCore($action->newItem); + if($old->equalsExact($new)){ + //filter out useless noise in 1.13 + return null; + } + switch($action->sourceType){ + case NetworkInventoryAction::SOURCE_CONTAINER: + if($action->windowId === ContainerIds::UI and $action->inventorySlot > 0){ + if($action->inventorySlot === 50){ + return null; //useless noise + } + if($action->inventorySlot >= 28 and $action->inventorySlot <= 31){ + $window = $player->getCraftingGrid(); + if($window->getGridWidth() !== CraftingGrid::SIZE_SMALL){ + throw new \UnexpectedValueException("Expected small crafting grid"); + } + $slot = $action->inventorySlot - 28; + }elseif($action->inventorySlot >= 32 and $action->inventorySlot <= 40){ + $window = $player->getCraftingGrid(); + if($window->getGridWidth() !== CraftingGrid::SIZE_BIG){ + throw new \UnexpectedValueException("Expected big crafting grid"); + } + $slot = $action->inventorySlot - 32; + }else{ + throw new \UnexpectedValueException("Unhandled magic UI slot offset $action->inventorySlot"); + } + }else{ + $window = $player->getNetworkSession()->getInvManager()->getWindow($action->windowId); + $slot = $action->inventorySlot; + } + if($window !== null){ + return new SlotChangeAction($window, $slot, $old, $new); + } + + throw new \UnexpectedValueException("No open container with window ID $action->windowId"); + case NetworkInventoryAction::SOURCE_WORLD: + if($action->inventorySlot !== NetworkInventoryAction::ACTION_MAGIC_SLOT_DROP_ITEM){ + throw new \UnexpectedValueException("Only expecting drop-item world actions from the client!"); + } + + return new DropItemAction($new); + case NetworkInventoryAction::SOURCE_CREATIVE: + switch($action->inventorySlot){ + case NetworkInventoryAction::ACTION_MAGIC_SLOT_CREATIVE_DELETE_ITEM: + return new DestroyItemAction($new); + case NetworkInventoryAction::ACTION_MAGIC_SLOT_CREATIVE_CREATE_ITEM: + return new CreateItemAction($new); + default: + throw new \UnexpectedValueException("Unexpected creative action type $action->inventorySlot"); + + } + case NetworkInventoryAction::SOURCE_TODO: + //These types need special handling. + switch($action->windowId){ + case NetworkInventoryAction::SOURCE_TYPE_CRAFTING_RESULT: + case NetworkInventoryAction::SOURCE_TYPE_CRAFTING_USE_INGREDIENT: + return null; + } + + //TODO: more stuff + throw new \UnexpectedValueException("No open container with window ID $action->windowId"); + default: + throw new \UnexpectedValueException("Unknown inventory source type $action->sourceType"); + } + } } \ No newline at end of file diff --git a/src/network/mcpe/handler/InGamePacketHandler.php b/src/network/mcpe/handler/InGamePacketHandler.php index 70c03c1c5..692f736e6 100644 --- a/src/network/mcpe/handler/InGamePacketHandler.php +++ b/src/network/mcpe/handler/InGamePacketHandler.php @@ -205,9 +205,10 @@ class InGamePacketHandler extends PacketHandler{ $isCrafting = false; $isFinalCraftingPart = false; + $converter = TypeConverter::getInstance(); foreach($data->getActions() as $networkInventoryAction){ - $old = TypeConverter::getInstance()->netItemStackToCore($networkInventoryAction->oldItem); - $new = TypeConverter::getInstance()->netItemStackToCore($networkInventoryAction->newItem); + $old = $converter->netItemStackToCore($networkInventoryAction->oldItem); + $new = $converter->netItemStackToCore($networkInventoryAction->newItem); if( $networkInventoryAction->sourceType === NetworkInventoryAction::SOURCE_CONTAINER and $networkInventoryAction->windowId === ContainerIds::UI and @@ -228,7 +229,7 @@ class InGamePacketHandler extends PacketHandler{ } try{ - $action = $networkInventoryAction->createInventoryAction($this->player); + $action = $converter->createInventoryAction($networkInventoryAction, $this->player); if($action !== null){ $actions[] = $action; } diff --git a/src/network/mcpe/protocol/types/inventory/NetworkInventoryAction.php b/src/network/mcpe/protocol/types/inventory/NetworkInventoryAction.php index 1ade37922..6d87dfc52 100644 --- a/src/network/mcpe/protocol/types/inventory/NetworkInventoryAction.php +++ b/src/network/mcpe/protocol/types/inventory/NetworkInventoryAction.php @@ -23,16 +23,8 @@ declare(strict_types=1); namespace pocketmine\network\mcpe\protocol\types\inventory; -use pocketmine\crafting\CraftingGrid; -use pocketmine\inventory\transaction\action\CreateItemAction; -use pocketmine\inventory\transaction\action\DestroyItemAction; -use pocketmine\inventory\transaction\action\DropItemAction; -use pocketmine\inventory\transaction\action\InventoryAction; -use pocketmine\inventory\transaction\action\SlotChangeAction; use pocketmine\network\BadPacketException; -use pocketmine\network\mcpe\convert\TypeConverter; use pocketmine\network\mcpe\serializer\NetworkBinaryStream; -use pocketmine\player\Player; use pocketmine\utils\BinaryDataException; class NetworkInventoryAction{ @@ -143,75 +135,4 @@ class NetworkInventoryAction{ $packet->putSlot($this->oldItem); $packet->putSlot($this->newItem); } - - /** - * @throws \UnexpectedValueException - */ - public function createInventoryAction(Player $player) : ?InventoryAction{ - $old = TypeConverter::getInstance()->netItemStackToCore($this->oldItem); - $new = TypeConverter::getInstance()->netItemStackToCore($this->newItem); - if($old->equalsExact($new)){ - //filter out useless noise in 1.13 - return null; - } - switch($this->sourceType){ - case self::SOURCE_CONTAINER: - if($this->windowId === ContainerIds::UI and $this->inventorySlot > 0){ - if($this->inventorySlot === 50){ - return null; //useless noise - } - if($this->inventorySlot >= 28 and $this->inventorySlot <= 31){ - $window = $player->getCraftingGrid(); - if($window->getGridWidth() !== CraftingGrid::SIZE_SMALL){ - throw new \UnexpectedValueException("Expected small crafting grid"); - } - $slot = $this->inventorySlot - 28; - }elseif($this->inventorySlot >= 32 and $this->inventorySlot <= 40){ - $window = $player->getCraftingGrid(); - if($window->getGridWidth() !== CraftingGrid::SIZE_BIG){ - throw new \UnexpectedValueException("Expected big crafting grid"); - } - $slot = $this->inventorySlot - 32; - }else{ - throw new \UnexpectedValueException("Unhandled magic UI slot offset $this->inventorySlot"); - } - }else{ - $window = $player->getNetworkSession()->getInvManager()->getWindow($this->windowId); - $slot = $this->inventorySlot; - } - if($window !== null){ - return new SlotChangeAction($window, $slot, $old, $new); - } - - throw new \UnexpectedValueException("No open container with window ID $this->windowId"); - case self::SOURCE_WORLD: - if($this->inventorySlot !== self::ACTION_MAGIC_SLOT_DROP_ITEM){ - throw new \UnexpectedValueException("Only expecting drop-item world actions from the client!"); - } - - return new DropItemAction($new); - case self::SOURCE_CREATIVE: - switch($this->inventorySlot){ - case self::ACTION_MAGIC_SLOT_CREATIVE_DELETE_ITEM: - return new DestroyItemAction($new); - case self::ACTION_MAGIC_SLOT_CREATIVE_CREATE_ITEM: - return new CreateItemAction($new); - default: - throw new \UnexpectedValueException("Unexpected creative action type $this->inventorySlot"); - - } - case self::SOURCE_TODO: - //These types need special handling. - switch($this->windowId){ - case self::SOURCE_TYPE_CRAFTING_RESULT: - case self::SOURCE_TYPE_CRAFTING_USE_INGREDIENT: - return null; - } - - //TODO: more stuff - throw new \UnexpectedValueException("No open container with window ID $this->windowId"); - default: - throw new \UnexpectedValueException("Unknown inventory source type $this->sourceType"); - } - } }