Start deglobalizing TypeConverter

there's a bunch of places we can't reach with this right now:

- particles
- sounds
- tile NBT
- entity metadata
- crafting data cache
- chunk encoding
- world block update encoding

this is a work in progress, but ultimately we want to get rid of these singletons entirely.
This commit is contained in:
Dylan K. Taylor 2023-05-06 17:47:09 +01:00
parent 7cdf6b0946
commit e0a6ec0c24
No known key found for this signature in database
GPG Key ID: 8927471A91CAFD3D
9 changed files with 50 additions and 26 deletions

View File

@ -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;

View File

@ -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([], []),

View File

@ -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(),

View File

@ -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()){

View File

@ -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

View File

@ -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())),

View File

@ -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);

View File

@ -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");

View File

@ -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
);