NetworkInventoryAction: move type translation to TypeConverter

This commit is contained in:
Dylan K. Taylor 2020-04-23 15:40:23 +01:00
parent 33f899f2fc
commit ebcfab4b61
3 changed files with 85 additions and 82 deletions

View File

@ -22,14 +22,24 @@ declare(strict_types=1);
namespace pocketmine\network\mcpe\convert; 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\Durable;
use pocketmine\item\Item; use pocketmine\item\Item;
use pocketmine\item\ItemFactory; use pocketmine\item\ItemFactory;
use pocketmine\item\ItemIds; use pocketmine\item\ItemIds;
use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\IntTag; 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\ItemStack;
use pocketmine\network\mcpe\protocol\types\inventory\NetworkInventoryAction;
use pocketmine\network\mcpe\protocol\types\recipe\RecipeIngredient; use pocketmine\network\mcpe\protocol\types\recipe\RecipeIngredient;
use pocketmine\player\Player;
class TypeConverter{ class TypeConverter{
private const DAMAGE_TAG = "Damage"; //TAG_Int private const DAMAGE_TAG = "Damage"; //TAG_Int
@ -121,4 +131,75 @@ class TypeConverter{
$compound $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");
}
}
} }

View File

@ -205,9 +205,10 @@ class InGamePacketHandler extends PacketHandler{
$isCrafting = false; $isCrafting = false;
$isFinalCraftingPart = false; $isFinalCraftingPart = false;
$converter = TypeConverter::getInstance();
foreach($data->getActions() as $networkInventoryAction){ foreach($data->getActions() as $networkInventoryAction){
$old = TypeConverter::getInstance()->netItemStackToCore($networkInventoryAction->oldItem); $old = $converter->netItemStackToCore($networkInventoryAction->oldItem);
$new = TypeConverter::getInstance()->netItemStackToCore($networkInventoryAction->newItem); $new = $converter->netItemStackToCore($networkInventoryAction->newItem);
if( if(
$networkInventoryAction->sourceType === NetworkInventoryAction::SOURCE_CONTAINER and $networkInventoryAction->sourceType === NetworkInventoryAction::SOURCE_CONTAINER and
$networkInventoryAction->windowId === ContainerIds::UI and $networkInventoryAction->windowId === ContainerIds::UI and
@ -228,7 +229,7 @@ class InGamePacketHandler extends PacketHandler{
} }
try{ try{
$action = $networkInventoryAction->createInventoryAction($this->player); $action = $converter->createInventoryAction($networkInventoryAction, $this->player);
if($action !== null){ if($action !== null){
$actions[] = $action; $actions[] = $action;
} }

View File

@ -23,16 +23,8 @@ declare(strict_types=1);
namespace pocketmine\network\mcpe\protocol\types\inventory; 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\BadPacketException;
use pocketmine\network\mcpe\convert\TypeConverter;
use pocketmine\network\mcpe\serializer\NetworkBinaryStream; use pocketmine\network\mcpe\serializer\NetworkBinaryStream;
use pocketmine\player\Player;
use pocketmine\utils\BinaryDataException; use pocketmine\utils\BinaryDataException;
class NetworkInventoryAction{ class NetworkInventoryAction{
@ -143,75 +135,4 @@ class NetworkInventoryAction{
$packet->putSlot($this->oldItem); $packet->putSlot($this->oldItem);
$packet->putSlot($this->newItem); $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");
}
}
} }