diff --git a/src/Server.php b/src/Server.php index 7bc67aa38..53c3c05a9 100644 --- a/src/Server.php +++ b/src/Server.php @@ -1174,11 +1174,12 @@ class Server{ bool $useQuery, PacketBroadcaster $packetBroadcaster, EntityEventBroadcaster $entityEventBroadcaster, - PacketSerializerContext $packetSerializerContext + PacketSerializerContext $packetSerializerContext, + TypeConverter $typeConverter ) : bool{ $prettyIp = $ipV6 ? "[$ip]" : $ip; try{ - $rakLibRegistered = $this->network->registerInterface(new RakLibInterface($this, $ip, $port, $ipV6, $packetBroadcaster, $entityEventBroadcaster, $packetSerializerContext)); + $rakLibRegistered = $this->network->registerInterface(new RakLibInterface($this, $ip, $port, $ipV6, $packetBroadcaster, $entityEventBroadcaster, $packetSerializerContext, $typeConverter)); }catch(NetworkInterfaceStartException $e){ $this->logger->emergency($this->language->translate(KnownTranslationFactory::pocketmine_server_networkStartFailed( $ip, @@ -1204,15 +1205,16 @@ class Server{ private function startupPrepareNetworkInterfaces() : bool{ $useQuery = $this->configGroup->getConfigBool("enable-query", true); - $packetSerializerContext = new PacketSerializerContext(TypeConverter::getInstance()->getItemTypeDictionary()); + $typeConverter = TypeConverter::getInstance(); + $packetSerializerContext = new PacketSerializerContext($typeConverter->getItemTypeDictionary()); $packetBroadcaster = new StandardPacketBroadcaster($this, $packetSerializerContext); - $entityEventBroadcaster = new StandardEntityEventBroadcaster($packetBroadcaster); + $entityEventBroadcaster = new StandardEntityEventBroadcaster($packetBroadcaster, $typeConverter); if( - !$this->startupPrepareConnectableNetworkInterfaces($this->getIp(), $this->getPort(), false, $useQuery, $packetBroadcaster, $entityEventBroadcaster, $packetSerializerContext) || + !$this->startupPrepareConnectableNetworkInterfaces($this->getIp(), $this->getPort(), false, $useQuery, $packetBroadcaster, $entityEventBroadcaster, $packetSerializerContext, $typeConverter) || ( $this->configGroup->getConfigBool("enable-ipv6", true) && - !$this->startupPrepareConnectableNetworkInterfaces($this->getIpV6(), $this->getPortV6(), true, $useQuery, $packetBroadcaster, $entityEventBroadcaster, $packetSerializerContext) + !$this->startupPrepareConnectableNetworkInterfaces($this->getIpV6(), $this->getPortV6(), true, $useQuery, $packetBroadcaster, $entityEventBroadcaster, $packetSerializerContext, $typeConverter) ) ){ return false; diff --git a/src/entity/Human.php b/src/entity/Human.php index 38e69724b..840ae7fc9 100644 --- a/src/entity/Human.php +++ b/src/entity/Human.php @@ -474,6 +474,7 @@ class Human extends Living implements ProjectileSource, InventoryHolder{ $networkSession->sendDataPacket(PlayerListPacket::add([PlayerListEntry::createAdditionEntry($this->uuid, $this->id, $this->getName(), SkinAdapterSingleton::get()->toSkinData($this->skin))])); } + $typeConverter = $networkSession->getTypeConverter(); $networkSession->sendDataPacket(AddPlayerPacket::create( $this->getUniqueId(), $this->getName(), @@ -484,7 +485,7 @@ class Human extends Living implements ProjectileSource, InventoryHolder{ $this->location->pitch, $this->location->yaw, $this->location->yaw, //TODO: head yaw - ItemStackWrapper::legacy(TypeConverter::getInstance()->coreItemStackToNet($this->getInventory()->getItemInHand())), + ItemStackWrapper::legacy($typeConverter->coreItemStackToNet($this->getInventory()->getItemInHand())), GameMode::SURVIVAL, $this->getAllNetworkData(), new PropertySyncData([], []), diff --git a/src/entity/object/ItemEntity.php b/src/entity/object/ItemEntity.php index 81682d3bb..3c95a9c45 100644 --- a/src/entity/object/ItemEntity.php +++ b/src/entity/object/ItemEntity.php @@ -285,10 +285,11 @@ class ItemEntity extends Entity{ } protected function sendSpawnPacket(Player $player) : void{ - $player->getNetworkSession()->sendDataPacket(AddItemActorPacket::create( + $networkSession = $player->getNetworkSession(); + $networkSession->sendDataPacket(AddItemActorPacket::create( $this->getId(), //TODO: entity unique ID $this->getId(), - ItemStackWrapper::legacy(TypeConverter::getInstance()->coreItemStackToNet($this->getItem())), + ItemStackWrapper::legacy($networkSession->getTypeConverter()->coreItemStackToNet($this->getItem())), $this->location->asVector3(), $this->getMotion(), $this->getAllNetworkData(), diff --git a/src/network/mcpe/InventoryManager.php b/src/network/mcpe/InventoryManager.php index fc7c6641f..d28235821 100644 --- a/src/network/mcpe/InventoryManager.php +++ b/src/network/mcpe/InventoryManager.php @@ -223,10 +223,11 @@ class InventoryManager{ } public function addTransactionPredictedSlotChanges(InventoryTransaction $tx) : void{ + $typeConverter = $this->session->getTypeConverter(); foreach($tx->getActions() as $action){ if($action instanceof SlotChangeAction){ //TODO: ItemStackRequestExecutor can probably build these predictions with much lower overhead - $itemStack = TypeConverter::getInstance()->coreItemStackToNet($action->getTargetItem()); + $itemStack = $typeConverter->coreItemStackToNet($action->getTargetItem()); $this->addPredictedSlotChange($action->getInventory(), $action->getSlot(), $itemStack); } } @@ -421,7 +422,7 @@ class InventoryManager{ //is cleared before removal. return; } - $currentItem = TypeConverter::getInstance()->coreItemStackToNet($inventory->getItem($slot)); + $currentItem = $this->session->getTypeConverter()->coreItemStackToNet($inventory->getItem($slot)); $clientSideItem = $inventoryEntry->predictions[$slot] ?? null; if($clientSideItem === null || !$clientSideItem->equals($currentItem)){ //no prediction or incorrect - do not associate this with the currently active itemstack request @@ -497,7 +498,7 @@ class InventoryManager{ $entry->predictions = []; $entry->pendingSyncs = []; $contents = []; - $typeConverter = TypeConverter::getInstance(); + $typeConverter = $this->session->getTypeConverter(); foreach($inventory->getContents(true) as $slot => $item){ $itemStack = $typeConverter->coreItemStackToNet($item); $info = $this->trackItemStack($entry, $slot, $itemStack, null); @@ -532,7 +533,7 @@ class InventoryManager{ } public function syncMismatchedPredictedSlotChanges() : void{ - $typeConverter = TypeConverter::getInstance(); + $typeConverter = $this->session->getTypeConverter(); foreach($this->inventories as $entry){ $inventory = $entry->inventory; foreach($entry->predictions as $slot => $expectedItem){ @@ -595,7 +596,7 @@ class InventoryManager{ $this->session->sendDataPacket(MobEquipmentPacket::create( $this->player->getId(), - new ItemStackWrapper($itemStackInfo->getStackId(), TypeConverter::getInstance()->coreItemStackToNet($playerInventory->getItemInHand())), + new ItemStackWrapper($itemStackInfo->getStackId(), $this->session->getTypeConverter()->coreItemStackToNet($playerInventory->getItemInHand())), $selected, $selected, ContainerIds::INVENTORY @@ -605,7 +606,7 @@ class InventoryManager{ } public function syncCreative() : void{ - $typeConverter = TypeConverter::getInstance(); + $typeConverter = $this->session->getTypeConverter(); $entries = []; if(!$this->player->isSpectator()){ diff --git a/src/network/mcpe/NetworkSession.php b/src/network/mcpe/NetworkSession.php index abab59825..60b0efc66 100644 --- a/src/network/mcpe/NetworkSession.php +++ b/src/network/mcpe/NetworkSession.php @@ -182,6 +182,7 @@ class NetworkSession{ private PacketBroadcaster $broadcaster, private EntityEventBroadcaster $entityEventBroadcaster, private Compressor $compressor, + private TypeConverter $typeConverter, private string $ip, private int $port ){ @@ -538,6 +539,8 @@ class NetworkSession{ return $this->compressor; } + public function getTypeConverter() : TypeConverter{ return $this->typeConverter; } + public function queueCompressed(CompressBatchPromise $payload, bool $immediate = false) : void{ Timings::$playerNetworkSend->startTiming(); try{ @@ -887,7 +890,7 @@ class NetworkSession{ } public function syncGameMode(GameMode $mode, bool $isRollback = false) : void{ - $this->sendDataPacket(SetPlayerGameTypePacket::create(TypeConverter::getInstance()->coreGameModeToProtocol($mode))); + $this->sendDataPacket(SetPlayerGameTypePacket::create($this->typeConverter->coreGameModeToProtocol($mode))); if($this->player !== null){ $this->syncAbilities($this->player); $this->syncAdventureSettings(); //TODO: we might be able to do this with the abilities packet alone diff --git a/src/network/mcpe/StandardEntityEventBroadcaster.php b/src/network/mcpe/StandardEntityEventBroadcaster.php index da0fac6ef..30ac628f6 100644 --- a/src/network/mcpe/StandardEntityEventBroadcaster.php +++ b/src/network/mcpe/StandardEntityEventBroadcaster.php @@ -51,7 +51,8 @@ use const SORT_NUMERIC; final class StandardEntityEventBroadcaster implements EntityEventBroadcaster{ public function __construct( - private StandardPacketBroadcaster $broadcaster + private StandardPacketBroadcaster $broadcaster, + private TypeConverter $typeConverter ){} /** @@ -103,7 +104,7 @@ final class StandardEntityEventBroadcaster implements EntityEventBroadcaster{ $inv = $mob->getInventory(); $this->sendDataPacket($recipients, MobEquipmentPacket::create( $mob->getId(), - ItemStackWrapper::legacy(TypeConverter::getInstance()->coreItemStackToNet($inv->getItemInHand())), + ItemStackWrapper::legacy($this->typeConverter->coreItemStackToNet($inv->getItemInHand())), $inv->getHeldItemIndex(), $inv->getHeldItemIndex(), ContainerIds::INVENTORY @@ -114,7 +115,7 @@ final class StandardEntityEventBroadcaster implements EntityEventBroadcaster{ $inv = $mob->getOffHandInventory(); $this->sendDataPacket($recipients, MobEquipmentPacket::create( $mob->getId(), - ItemStackWrapper::legacy(TypeConverter::getInstance()->coreItemStackToNet($inv->getItem(0))), + ItemStackWrapper::legacy($this->typeConverter->coreItemStackToNet($inv->getItem(0))), 0, 0, ContainerIds::OFFHAND @@ -123,7 +124,7 @@ final class StandardEntityEventBroadcaster implements EntityEventBroadcaster{ public function onMobArmorChange(array $recipients, Living $mob) : void{ $inv = $mob->getArmorInventory(); - $converter = TypeConverter::getInstance(); + $converter = $this->typeConverter; $this->sendDataPacket($recipients, MobArmorEquipmentPacket::create( $mob->getId(), ItemStackWrapper::legacy($converter->coreItemStackToNet($inv->getHelmet())), diff --git a/src/network/mcpe/handler/InGamePacketHandler.php b/src/network/mcpe/handler/InGamePacketHandler.php index d8b6caf1f..a062dfff9 100644 --- a/src/network/mcpe/handler/InGamePacketHandler.php +++ b/src/network/mcpe/handler/InGamePacketHandler.php @@ -443,7 +443,7 @@ class InGamePacketHandler extends PacketHandler{ if($sourceSlotItem->getCount() < $droppedCount){ return false; } - $serverItemStack = TypeConverter::getInstance()->coreItemStackToNet($sourceSlotItem); + $serverItemStack = $this->session->getTypeConverter()->coreItemStackToNet($sourceSlotItem); //because the client doesn't tell us the expected itemstack ID, we have to deep-compare our known //itemstack info with the one the client sent. This is costly, but we don't have any other option :( if(!$serverItemStack->equals($clientItemStack)){ @@ -776,7 +776,7 @@ class InGamePacketHandler extends PacketHandler{ } public function handleSetPlayerGameType(SetPlayerGameTypePacket $packet) : bool{ - $gameMode = TypeConverter::getInstance()->protocolGameModeToCore($packet->gamemode); + $gameMode = $this->session->getTypeConverter()->protocolGameModeToCore($packet->gamemode); if($gameMode === null || !$gameMode->equals($this->player->getGamemode())){ //Set this back to default. TODO: handle this properly $this->session->syncGameMode($this->player->getGamemode(), true); diff --git a/src/network/mcpe/handler/PreSpawnPacketHandler.php b/src/network/mcpe/handler/PreSpawnPacketHandler.php index 0ba686bed..9e0adf5e1 100644 --- a/src/network/mcpe/handler/PreSpawnPacketHandler.php +++ b/src/network/mcpe/handler/PreSpawnPacketHandler.php @@ -65,11 +65,13 @@ class PreSpawnPacketHandler extends PacketHandler{ $location = $this->player->getLocation(); $world = $location->getWorld(); + $typeConverter = $this->session->getTypeConverter(); + $this->session->getLogger()->debug("Preparing StartGamePacket"); $levelSettings = new LevelSettings(); $levelSettings->seed = -1; $levelSettings->spawnSettings = new SpawnSettings(SpawnSettings::BIOME_TYPE_DEFAULT, "", DimensionIds::OVERWORLD); //TODO: implement this properly - $levelSettings->worldGamemode = TypeConverter::getInstance()->coreGameModeToProtocol($this->server->getGamemode()); + $levelSettings->worldGamemode = $typeConverter->coreGameModeToProtocol($this->server->getGamemode()); $levelSettings->difficulty = $world->getDifficulty(); $levelSettings->spawnPosition = BlockPosition::fromVector3($world->getSpawnLocation()); $levelSettings->hasAchievementsDisabled = true; @@ -86,7 +88,7 @@ class PreSpawnPacketHandler extends PacketHandler{ $this->session->sendDataPacket(StartGamePacket::create( $this->player->getId(), $this->player->getId(), - TypeConverter::getInstance()->coreGameModeToProtocol($this->player->getGamemode()), + $typeConverter->coreGameModeToProtocol($this->player->getGamemode()), $this->player->getOffsetPosition($location), $location->pitch, $location->yaw, @@ -107,7 +109,7 @@ class PreSpawnPacketHandler extends PacketHandler{ false, [], 0, - TypeConverter::getInstance()->getItemTypeDictionary()->getEntries(), + $typeConverter->getItemTypeDictionary()->getEntries(), )); $this->session->getLogger()->debug("Sending actor identifiers"); diff --git a/src/network/mcpe/raklib/RakLibInterface.php b/src/network/mcpe/raklib/RakLibInterface.php index 82d881239..6a9f0f0b0 100644 --- a/src/network/mcpe/raklib/RakLibInterface.php +++ b/src/network/mcpe/raklib/RakLibInterface.php @@ -26,6 +26,7 @@ namespace pocketmine\network\mcpe\raklib; use pocketmine\lang\KnownTranslationFactory; use pocketmine\network\AdvancedNetworkInterface; use pocketmine\network\mcpe\compression\ZlibCompressor; +use pocketmine\network\mcpe\convert\TypeConverter; use pocketmine\network\mcpe\EntityEventBroadcaster; use pocketmine\network\mcpe\NetworkSession; use pocketmine\network\mcpe\PacketBroadcaster; @@ -82,12 +83,23 @@ class RakLibInterface implements ServerEventListener, AdvancedNetworkInterface{ private PacketBroadcaster $packetBroadcaster; private EntityEventBroadcaster $entityEventBroadcaster; private PacketSerializerContext $packetSerializerContext; + private TypeConverter $typeConverter; - public function __construct(Server $server, string $ip, int $port, bool $ipV6, PacketBroadcaster $packetBroadcaster, EntityEventBroadcaster $entityEventBroadcaster, PacketSerializerContext $packetSerializerContext){ + public function __construct( + Server $server, + string $ip, + int $port, + bool $ipV6, + PacketBroadcaster $packetBroadcaster, + EntityEventBroadcaster $entityEventBroadcaster, + PacketSerializerContext $packetSerializerContext, + TypeConverter $typeConverter + ){ $this->server = $server; $this->packetBroadcaster = $packetBroadcaster; $this->packetSerializerContext = $packetSerializerContext; $this->entityEventBroadcaster = $entityEventBroadcaster; + $this->typeConverter = $typeConverter; $this->rakServerId = mt_rand(0, PHP_INT_MAX); @@ -183,6 +195,7 @@ class RakLibInterface implements ServerEventListener, AdvancedNetworkInterface{ $this->packetBroadcaster, $this->entityEventBroadcaster, ZlibCompressor::getInstance(), //TODO: this shouldn't be hardcoded, but we might need the RakNet protocol version to select it + $this->typeConverter, $address, $port );