NetworkSession: Fixed InventoryManager nullability disaster

fixes #4277
fixes #4275
fixes #3139
This commit is contained in:
Dylan K. Taylor
2021-06-26 17:44:42 +01:00
parent e43bca95bf
commit 0910054c41
8 changed files with 74 additions and 48 deletions

View File

@@ -672,7 +672,7 @@ class NetworkSession{
}
private function beginSpawnSequence() : void{
$this->setHandler(new PreSpawnPacketHandler($this->server, $this->player, $this));
$this->setHandler(new PreSpawnPacketHandler($this->server, $this->player, $this, $this->invManager));
$this->player->setImmobile(); //TODO: HACK: fix client-side falling pre-spawn
$this->logger->debug("Waiting for chunk radius request");
@@ -691,7 +691,7 @@ class NetworkSession{
$this->player->setImmobile(false); //TODO: HACK: we set this during the spawn sequence to prevent the client sending junk movements
$this->player->doFirstSpawn();
$this->forceAsyncCompression = false;
$this->setHandler(new InGamePacketHandler($this->player, $this));
$this->setHandler(new InGamePacketHandler($this->player, $this, $this->invManager));
}
public function onServerDeath() : void{
@@ -705,7 +705,7 @@ class NetworkSession{
$this->syncAdventureSettings($this->player);
$this->invManager->syncAll();
$this->setHandler(new InGamePacketHandler($this->player, $this));
$this->setHandler(new InGamePacketHandler($this->player, $this, $this->invManager));
}
public function syncMovement(Vector3 $pos, ?float $yaw = null, ?float $pitch = null, int $mode = MovePlayerPacket::MODE_NORMAL) : void{
@@ -937,7 +937,7 @@ class NetworkSession{
$this->sendDataPacket(SetDifficultyPacket::create($worldDifficulty));
}
public function getInvManager() : InventoryManager{
public function getInvManager() : ?InventoryManager{
return $this->invManager;
}

View File

@@ -39,6 +39,7 @@ use pocketmine\item\ItemFactory;
use pocketmine\item\ItemIds;
use pocketmine\nbt\tag\CompoundTag;
use pocketmine\nbt\tag\IntTag;
use pocketmine\network\mcpe\InventoryManager;
use pocketmine\network\mcpe\protocol\types\GameMode as ProtocolGameMode;
use pocketmine\network\mcpe\protocol\types\inventory\ContainerIds;
use pocketmine\network\mcpe\protocol\types\inventory\ItemStack;
@@ -240,7 +241,7 @@ class TypeConverter{
/**
* @throws \UnexpectedValueException
*/
public function createInventoryAction(NetworkInventoryAction $action, Player $player) : ?InventoryAction{
public function createInventoryAction(NetworkInventoryAction $action, Player $player, InventoryManager $inventoryManager) : ?InventoryAction{
if($action->oldItem->getItemStack()->equals($action->newItem->getItemStack())){
//filter out useless noise in 1.13
return null;
@@ -276,7 +277,7 @@ class TypeConverter{
}
[$slot, $window] = $mapped;
}else{
$window = $player->getNetworkSession()->getInvManager()->getWindow($action->windowId);
$window = $inventoryManager->getWindow($action->windowId);
$slot = $action->inventorySlot;
}
if($window !== null){

View File

@@ -143,9 +143,12 @@ class InGamePacketHandler extends PacketHandler{
*/
protected $openHardcodedWindows = [];
public function __construct(Player $player, NetworkSession $session){
private InventoryManager $inventoryManager;
public function __construct(Player $player, NetworkSession $session, InventoryManager $inventoryManager){
$this->player = $player;
$this->session = $session;
$this->inventoryManager = $inventoryManager;
}
public function handleText(TextPacket $packet) : bool{
@@ -224,7 +227,7 @@ class InGamePacketHandler extends PacketHandler{
$result = $this->handleNormalTransaction($packet->trData);
}elseif($packet->trData instanceof MismatchTransactionData){
$this->session->getLogger()->debug("Mismatch transaction received");
$this->session->getInvManager()->syncAll();
$this->inventoryManager->syncAll();
$result = true;
}elseif($packet->trData instanceof UseItemTransactionData){
$result = $this->handleUseItemTransaction($packet->trData);
@@ -235,7 +238,7 @@ class InGamePacketHandler extends PacketHandler{
}
if(!$result){
$this->session->getInvManager()->syncAll();
$this->inventoryManager->syncAll();
}
return $result;
}
@@ -265,7 +268,7 @@ class InGamePacketHandler extends PacketHandler{
}
try{
$action = $converter->createInventoryAction($networkInventoryAction, $this->player);
$action = $converter->createInventoryAction($networkInventoryAction, $this->player, $this->inventoryManager);
if($action !== null){
$actions[] = $action;
}
@@ -293,14 +296,14 @@ class InGamePacketHandler extends PacketHandler{
return true;
}
try{
$this->session->getInvManager()->onTransactionStart($this->craftingTransaction);
$this->inventoryManager->onTransactionStart($this->craftingTransaction);
$this->craftingTransaction->execute();
}catch(TransactionException $e){
$this->session->getLogger()->debug("Failed to execute crafting transaction: " . $e->getMessage());
//TODO: only sync slots that the client tried to change
foreach($this->craftingTransaction->getInventories() as $inventory){
$this->session->getInvManager()->syncContents($inventory);
$this->inventoryManager->syncContents($inventory);
}
/*
* TODO: HACK!
@@ -328,7 +331,7 @@ class InGamePacketHandler extends PacketHandler{
}
$transaction = new InventoryTransaction($this->player, $actions);
$this->session->getInvManager()->onTransactionStart($transaction);
$this->inventoryManager->onTransactionStart($transaction);
try{
$transaction->execute();
}catch(TransactionException $e){
@@ -337,7 +340,7 @@ class InGamePacketHandler extends PacketHandler{
$logger->debug("Actions: " . json_encode($data->getActions()));
foreach($transaction->getInventories() as $inventory){
$this->session->getInvManager()->syncContents($inventory);
$this->inventoryManager->syncContents($inventory);
}
return false;
@@ -392,12 +395,12 @@ class InGamePacketHandler extends PacketHandler{
case UseItemTransactionData::ACTION_CLICK_AIR:
if($this->player->isUsingItem()){
if(!$this->player->consumeHeldItem()){
$this->session->getInvManager()->syncSlot($this->player->getInventory(), $this->player->getInventory()->getHeldItemIndex());
$this->inventoryManager->syncSlot($this->player->getInventory(), $this->player->getInventory()->getHeldItemIndex());
}
return true;
}
if(!$this->player->useHeldItem()){
$this->session->getInvManager()->syncSlot($this->player->getInventory(), $this->player->getInventory()->getHeldItemIndex());
$this->inventoryManager->syncSlot($this->player->getInventory(), $this->player->getInventory()->getHeldItemIndex());
}
return true;
}
@@ -409,7 +412,7 @@ class InGamePacketHandler extends PacketHandler{
* Internal function used to execute rollbacks when an action fails on a block.
*/
private function onFailedBlockAction(Vector3 $blockPos, ?int $face) : void{
$this->session->getInvManager()->syncSlot($this->player->getInventory(), $this->player->getInventory()->getHeldItemIndex());
$this->inventoryManager->syncSlot($this->player->getInventory(), $this->player->getInventory()->getHeldItemIndex());
if($blockPos->distanceSquared($this->player->getLocation()) < 10000){
$blocks = $blockPos->sidesArray();
if($face !== null){
@@ -436,12 +439,12 @@ class InGamePacketHandler extends PacketHandler{
switch($data->getActionType()){
case UseItemOnEntityTransactionData::ACTION_INTERACT:
if(!$this->player->interactEntity($target, $data->getClickPos())){
$this->session->getInvManager()->syncSlot($this->player->getInventory(), $this->player->getInventory()->getHeldItemIndex());
$this->inventoryManager->syncSlot($this->player->getInventory(), $this->player->getInventory()->getHeldItemIndex());
}
return true;
case UseItemOnEntityTransactionData::ACTION_ATTACK:
if(!$this->player->attackEntity($target)){
$this->session->getInvManager()->syncSlot($this->player->getInventory(), $this->player->getInventory()->getHeldItemIndex());
$this->inventoryManager->syncSlot($this->player->getInventory(), $this->player->getInventory()->getHeldItemIndex());
}
return true;
}
@@ -454,7 +457,7 @@ class InGamePacketHandler extends PacketHandler{
switch($data->getActionType()){
case ReleaseItemTransactionData::ACTION_RELEASE:
if(!$this->player->releaseHeldItem()){
$this->session->getInvManager()->syncContents($this->player->getInventory());
$this->inventoryManager->syncContents($this->player->getInventory());
}
return true;
}
@@ -467,9 +470,9 @@ class InGamePacketHandler extends PacketHandler{
return true; //this happens when we put an item into the offhand
}
if($packet->windowId === ContainerIds::INVENTORY){
$this->session->getInvManager()->onClientSelectHotbarSlot($packet->hotbarSlot);
$this->inventoryManager->onClientSelectHotbarSlot($packet->hotbarSlot);
if(!$this->player->selectHotbarSlot($packet->hotbarSlot)){
$this->session->getInvManager()->syncSelectedHotbarSlot();
$this->inventoryManager->syncSelectedHotbarSlot();
}
return true;
}
@@ -603,7 +606,7 @@ class InGamePacketHandler extends PacketHandler{
if(array_key_exists($packet->windowId, $this->openHardcodedWindows)){
unset($this->openHardcodedWindows[$packet->windowId]);
}else{
$this->session->getInvManager()->onClientRemoveWindow($packet->windowId);
$this->inventoryManager->onClientRemoveWindow($packet->windowId);
}
$this->session->sendDataPacket(ContainerClosePacket::create($packet->windowId, false));

View File

@@ -27,6 +27,7 @@ use pocketmine\network\mcpe\cache\CraftingDataCache;
use pocketmine\network\mcpe\cache\StaticPacketCache;
use pocketmine\network\mcpe\convert\GlobalItemTypeDictionary;
use pocketmine\network\mcpe\convert\TypeConverter;
use pocketmine\network\mcpe\InventoryManager;
use pocketmine\network\mcpe\NetworkSession;
use pocketmine\network\mcpe\protocol\RequestChunkRadiusPacket;
use pocketmine\network\mcpe\protocol\StartGamePacket;
@@ -53,10 +54,13 @@ class PreSpawnPacketHandler extends PacketHandler{
/** @var NetworkSession */
private $session;
public function __construct(Server $server, Player $player, NetworkSession $session){
private InventoryManager $inventoryManager;
public function __construct(Server $server, Player $player, NetworkSession $session, InventoryManager $inventoryManager){
$this->player = $player;
$this->server = $server;
$this->session = $session;
$this->inventoryManager = $inventoryManager;
}
public function setUp() : void{
@@ -104,9 +108,9 @@ class PreSpawnPacketHandler extends PacketHandler{
}
$this->player->sendData([$this->player]);
$this->session->getInvManager()->syncAll();
$this->session->getInvManager()->syncCreative();
$this->session->getInvManager()->syncSelectedHotbarSlot();
$this->inventoryManager->syncAll();
$this->inventoryManager->syncCreative();
$this->inventoryManager->syncSelectedHotbarSlot();
$this->session->sendDataPacket(CraftingDataCache::getInstance()->getCache($this->server->getCraftingManager()));
$this->session->syncPlayerList($this->server->getOnlinePlayers());