diff --git a/src/entity/Entity.php b/src/entity/Entity.php index ceb5a97b1..6289a896b 100644 --- a/src/entity/Entity.php +++ b/src/entity/Entity.php @@ -1418,20 +1418,21 @@ abstract class Entity{ * Called by spawnTo() to send whatever packets needed to spawn the entity to the client. */ protected function sendSpawnPacket(Player $player) : void{ - $pk = new AddActorPacket(); - $pk->actorRuntimeId = $this->getId(); - $pk->type = static::getNetworkTypeId(); - $pk->position = $this->location->asVector3(); - $pk->motion = $this->getMotion(); - $pk->yaw = $this->location->yaw; - $pk->headYaw = $this->location->yaw; //TODO - $pk->pitch = $this->location->pitch; - $pk->attributes = array_map(function(Attribute $attr) : NetworkAttribute{ - return new NetworkAttribute($attr->getId(), $attr->getMinValue(), $attr->getMaxValue(), $attr->getValue(), $attr->getDefaultValue()); - }, $this->attributeMap->getAll()); - $pk->metadata = $this->getAllNetworkData(); - - $player->getNetworkSession()->sendDataPacket($pk); + $player->getNetworkSession()->sendDataPacket(AddActorPacket::create( + $this->getId(), //TODO: actor unique ID + $this->getId(), + static::getNetworkTypeId(), + $this->location->asVector3(), + $this->getMotion(), + $this->location->pitch, + $this->location->yaw, + $this->location->yaw, //TODO: head yaw + array_map(function(Attribute $attr) : NetworkAttribute{ + return new NetworkAttribute($attr->getId(), $attr->getMinValue(), $attr->getMaxValue(), $attr->getValue(), $attr->getDefaultValue()); + }, $this->attributeMap->getAll()), + $this->getAllNetworkData(), + [] //TODO: entity links + )); } public function spawnTo(Player $player) : void{ diff --git a/src/entity/Human.php b/src/entity/Human.php index c953ffb47..c77de5005 100644 --- a/src/entity/Human.php +++ b/src/entity/Human.php @@ -47,8 +47,10 @@ use pocketmine\nbt\tag\StringTag; use pocketmine\network\mcpe\convert\SkinAdapterSingleton; use pocketmine\network\mcpe\convert\TypeConverter; use pocketmine\network\mcpe\protocol\AddPlayerPacket; +use pocketmine\network\mcpe\protocol\AdventureSettingsPacket; use pocketmine\network\mcpe\protocol\PlayerListPacket; use pocketmine\network\mcpe\protocol\PlayerSkinPacket; +use pocketmine\network\mcpe\protocol\types\DeviceOS; use pocketmine\network\mcpe\protocol\types\entity\EntityIds; use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataProperties; use pocketmine\network\mcpe\protocol\types\entity\StringMetadataProperty; @@ -444,17 +446,24 @@ class Human extends Living implements ProjectileSource, InventoryHolder{ $player->getNetworkSession()->sendDataPacket(PlayerListPacket::add([PlayerListEntry::createAdditionEntry($this->uuid, $this->id, $this->getName(), SkinAdapterSingleton::get()->toSkinData($this->skin))])); } - $pk = new AddPlayerPacket(); - $pk->uuid = $this->getUniqueId(); - $pk->username = $this->getName(); - $pk->actorRuntimeId = $this->getId(); - $pk->position = $this->location->asVector3(); - $pk->motion = $this->getMotion(); - $pk->yaw = $this->location->yaw; - $pk->pitch = $this->location->pitch; - $pk->item = ItemStackWrapper::legacy(TypeConverter::getInstance()->coreItemStackToNet($this->getInventory()->getItemInHand())); - $pk->metadata = $this->getAllNetworkData(); - $player->getNetworkSession()->sendDataPacket($pk); + $player->getNetworkSession()->sendDataPacket(AddPlayerPacket::create( + $this->getUniqueId(), + $this->getName(), + $this->getId(), //TODO: actor unique ID + $this->getId(), + "", + $this->location->asVector3(), + $this->getMotion(), + $this->location->pitch, + $this->location->yaw, + $this->location->yaw, //TODO: head yaw + ItemStackWrapper::legacy(TypeConverter::getInstance()->coreItemStackToNet($this->getInventory()->getItemInHand())), + $this->getAllNetworkData(), + AdventureSettingsPacket::create(0, 0, 0, 0, 0, $this->getId()), //TODO + [], //TODO: entity links + "", //device ID (we intentionally don't send this - secvuln) + DeviceOS::UNKNOWN //we intentionally don't send this (secvuln) + )); //TODO: Hack for MCPE 1.2.13: DATA_NAMETAG is useless in AddPlayerPacket, so it has to be sent separately $this->sendData([$player], [EntityMetadataProperties::NAMETAG => new StringMetadataProperty($this->getNameTag())]); diff --git a/src/entity/object/ItemEntity.php b/src/entity/object/ItemEntity.php index e9c71c6c2..899cbc279 100644 --- a/src/entity/object/ItemEntity.php +++ b/src/entity/object/ItemEntity.php @@ -206,14 +206,15 @@ class ItemEntity extends Entity{ } protected function sendSpawnPacket(Player $player) : void{ - $pk = new AddItemActorPacket(); - $pk->actorRuntimeId = $this->getId(); - $pk->position = $this->location->asVector3(); - $pk->motion = $this->getMotion(); - $pk->item = ItemStackWrapper::legacy(TypeConverter::getInstance()->coreItemStackToNet($this->getItem())); - $pk->metadata = $this->getAllNetworkData(); - - $player->getNetworkSession()->sendDataPacket($pk); + $player->getNetworkSession()->sendDataPacket(AddItemActorPacket::create( + $this->getId(), //TODO: entity unique ID + $this->getId(), + ItemStackWrapper::legacy(TypeConverter::getInstance()->coreItemStackToNet($this->getItem())), + $this->location->asVector3(), + $this->getMotion(), + $this->getAllNetworkData(), + false //TODO: I have no idea what this is needed for, but right now we don't support fishing anyway + )); } public function getOffsetPosition(Vector3 $vector3) : Vector3{ diff --git a/src/entity/object/Painting.php b/src/entity/object/Painting.php index fa031cb98..a95560e24 100644 --- a/src/entity/object/Painting.php +++ b/src/entity/object/Painting.php @@ -149,17 +149,17 @@ class Painting extends Entity{ } protected function sendSpawnPacket(Player $player) : void{ - $pk = new AddPaintingPacket(); - $pk->actorRuntimeId = $this->getId(); - $pk->position = new Vector3( - ($this->boundingBox->minX + $this->boundingBox->maxX) / 2, - ($this->boundingBox->minY + $this->boundingBox->maxY) / 2, - ($this->boundingBox->minZ + $this->boundingBox->maxZ) / 2 - ); - $pk->direction = self::FACING_TO_DATA[$this->facing]; - $pk->title = $this->motive->getName(); - - $player->getNetworkSession()->sendDataPacket($pk); + $player->getNetworkSession()->sendDataPacket(AddPaintingPacket::create( + $this->getId(), //TODO: entity unique ID + $this->getId(), + new Vector3( + ($this->boundingBox->minX + $this->boundingBox->maxX) / 2, + ($this->boundingBox->minY + $this->boundingBox->maxY) / 2, + ($this->boundingBox->minZ + $this->boundingBox->maxZ) / 2 + ), + self::FACING_TO_DATA[$this->facing], + $this->motive->getName() + )); } /** diff --git a/src/network/mcpe/NetworkSession.php b/src/network/mcpe/NetworkSession.php index 720e99349..2ca46db0e 100644 --- a/src/network/mcpe/NetworkSession.php +++ b/src/network/mcpe/NetworkSession.php @@ -776,7 +776,15 @@ class NetworkSession{ * TODO: make this less specialized */ public function syncAdventureSettings(Player $for) : void{ - $pk = new AdventureSettingsPacket(); + $isOp = $for->hasPermission(DefaultPermissions::ROOT_OPERATOR); + $pk = AdventureSettingsPacket::create( + 0, + $isOp ? AdventureSettingsPacket::PERMISSION_OPERATOR : AdventureSettingsPacket::PERMISSION_NORMAL, + 0, + $isOp ? PlayerPermissions::OPERATOR : PlayerPermissions::MEMBER, + 0, + $for->getId() + ); $pk->setFlag(AdventureSettingsPacket::WORLD_IMMUTABLE, $for->isSpectator()); $pk->setFlag(AdventureSettingsPacket::NO_PVP, $for->isSpectator()); @@ -787,11 +795,6 @@ class NetworkSession{ //TODO: permission flags - $isOp = $for->hasPermission(DefaultPermissions::ROOT_OPERATOR); - $pk->commandPermission = ($isOp ? AdventureSettingsPacket::PERMISSION_OPERATOR : AdventureSettingsPacket::PERMISSION_NORMAL); - $pk->playerPermission = ($isOp ? PlayerPermissions::OPERATOR : PlayerPermissions::MEMBER); - $pk->targetActorUniqueId = $for->getId(); - $this->sendDataPacket($pk); } @@ -828,9 +831,9 @@ class NetworkSession{ } public function syncAvailableCommands() : void{ - $pk = new AvailableCommandsPacket(); + $commandData = []; foreach($this->server->getCommandMap()->getCommands() as $name => $command){ - if(isset($pk->commandData[$command->getName()]) or $command->getName() === "help" or !$command->testPermissionSilent($this->player)){ + if(isset($commandData[$command->getName()]) or $command->getName() === "help" or !$command->testPermissionSilent($this->player)){ continue; } @@ -857,10 +860,10 @@ class NetworkSession{ ] ); - $pk->commandData[$command->getName()] = $data; + $commandData[$command->getName()] = $data; } - $this->sendDataPacket($pk); + $this->sendDataPacket(AvailableCommandsPacket::create($commandData, [], [], [])); } public function onRawChatMessage(string $message) : void{ diff --git a/src/network/mcpe/cache/CraftingDataCache.php b/src/network/mcpe/cache/CraftingDataCache.php index 68414e835..369a45039 100644 --- a/src/network/mcpe/cache/CraftingDataCache.php +++ b/src/network/mcpe/cache/CraftingDataCache.php @@ -71,15 +71,14 @@ final class CraftingDataCache{ */ private function buildCraftingDataCache(CraftingManager $manager) : CraftingDataPacket{ Timings::$craftingDataCacheRebuild->startTiming(); - $pk = new CraftingDataPacket(); - $pk->cleanRecipes = true; $counter = 0; $nullUUID = Uuid::fromString(Uuid::NIL); $converter = TypeConverter::getInstance(); + $recipesWithTypeIds = []; foreach($manager->getShapelessRecipes() as $list){ foreach($list as $recipe){ - $pk->recipesWithTypeIds[] = new ProtocolShapelessRecipe( + $recipesWithTypeIds[] = new ProtocolShapelessRecipe( CraftingDataPacket::ENTRY_SHAPELESS, Binary::writeInt(++$counter), array_map(function(Item $item) use ($converter) : RecipeIngredient{ @@ -104,7 +103,7 @@ final class CraftingDataCache{ $inputs[$row][$column] = $converter->coreItemStackToRecipeIngredient($recipe->getIngredient($column, $row)); } } - $pk->recipesWithTypeIds[] = $r = new ProtocolShapedRecipe( + $recipesWithTypeIds[] = $r = new ProtocolShapedRecipe( CraftingDataPacket::ENTRY_SHAPED, Binary::writeInt(++$counter), $inputs, @@ -128,7 +127,7 @@ final class CraftingDataCache{ }; foreach($manager->getFurnaceRecipeManager($furnaceType)->getAll() as $recipe){ $input = $converter->coreItemStackToNet($recipe->getInput()); - $pk->recipesWithTypeIds[] = new ProtocolFurnaceRecipe( + $recipesWithTypeIds[] = new ProtocolFurnaceRecipe( CraftingDataPacket::ENTRY_FURNACE_DATA, $input->getId(), $input->getMeta(), @@ -139,6 +138,6 @@ final class CraftingDataCache{ } Timings::$craftingDataCacheRebuild->stopTiming(); - return $pk; + return CraftingDataPacket::create($recipesWithTypeIds, [], [], [], true); } } diff --git a/src/world/particle/FloatingTextParticle.php b/src/world/particle/FloatingTextParticle.php index bac075975..1fe3ee008 100644 --- a/src/world/particle/FloatingTextParticle.php +++ b/src/world/particle/FloatingTextParticle.php @@ -28,8 +28,10 @@ use pocketmine\entity\Skin; use pocketmine\math\Vector3; use pocketmine\network\mcpe\convert\SkinAdapterSingleton; use pocketmine\network\mcpe\protocol\AddPlayerPacket; +use pocketmine\network\mcpe\protocol\AdventureSettingsPacket; use pocketmine\network\mcpe\protocol\PlayerListPacket; use pocketmine\network\mcpe\protocol\RemoveActorPacket; +use pocketmine\network\mcpe\protocol\types\DeviceOS; use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataFlags; use pocketmine\network\mcpe\protocol\types\entity\EntityMetadataProperties; use pocketmine\network\mcpe\protocol\types\entity\FloatMetadataProperty; @@ -96,22 +98,31 @@ class FloatingTextParticle implements Particle{ $p[] = PlayerListPacket::add([PlayerListEntry::createAdditionEntry($uuid, $this->entityId, $name, SkinAdapterSingleton::get()->toSkinData(new Skin("Standard_Custom", str_repeat("\x00", 8192))))]); - $pk = new AddPlayerPacket(); - $pk->uuid = $uuid; - $pk->username = $name; - $pk->actorRuntimeId = $this->entityId; - $pk->position = $pos; //TODO: check offset - $pk->item = ItemStackWrapper::legacy(ItemStack::null()); - - $flags = ( + $actorFlags = ( 1 << EntityMetadataFlags::IMMOBILE ); - $pk->metadata = [ - EntityMetadataProperties::FLAGS => new LongMetadataProperty($flags), + $actorMetadata = [ + EntityMetadataProperties::FLAGS => new LongMetadataProperty($actorFlags), EntityMetadataProperties::SCALE => new FloatMetadataProperty(0.01) //zero causes problems on debug builds ]; - - $p[] = $pk; + $p[] = AddPlayerPacket::create( + $uuid, + $name, + $this->entityId, //TODO: actor unique ID + $this->entityId, + "", + $pos, //TODO: check offset + null, + 0, + 0, + 0, + ItemStackWrapper::legacy(ItemStack::null()), + $actorMetadata, + AdventureSettingsPacket::create(0, 0, 0, 0, 0, $this->entityId), + [], + "", + DeviceOS::UNKNOWN + ); $p[] = PlayerListPacket::remove([PlayerListEntry::createRemovalEntry($uuid)]); }