diff --git a/build/make-release.php b/build/make-release.php index a1328b8ca..f23a036e1 100644 --- a/build/make-release.php +++ b/build/make-release.php @@ -39,7 +39,11 @@ use const STDIN; require_once dirname(__DIR__) . '/src/pocketmine/VersionInfo.php'; require_once dirname(__DIR__) . '/vendor/autoload.php'; -$currentVer = new VersionString(BASE_VERSION); +if(isset($argv[1])){ + $currentVer = new VersionString($argv[1]); +}else{ + $currentVer = new VersionString(BASE_VERSION); +} $nextVer = new VersionString(sprintf( "%u.%u.%u", $currentVer->getMajor(), @@ -47,27 +51,31 @@ $nextVer = new VersionString(sprintf( $currentVer->getPatch() + 1 )); - +function replaceVersion(string $versionInfoPath, string $newVersion, bool $isDev) : void{ + $versionInfo = file_get_contents($versionInfoPath); + $versionInfo = preg_replace( + $pattern = '/^const BASE_VERSION = "(\d+)\.(\d+)\.(\d+)(?:-(.*))?";$/m', + 'const BASE_VERSION = "' . $newVersion . '";', + $versionInfo + ); + $versionInfo = preg_replace( + '/^const IS_DEVELOPMENT_BUILD = (?:true|false);$/m', + 'const IS_DEVELOPMENT_BUILD = ' . ($isDev ? 'true' : 'false'). ';', + $versionInfo + ); + file_put_contents($versionInfoPath, $versionInfo); +} $versionInfoPath = dirname(__DIR__) . '/src/pocketmine/VersionInfo.php'; -$versionInfo = file_get_contents($versionInfoPath); +replaceVersion($versionInfoPath, $currentVer->getBaseVersion(), false); -file_put_contents($versionInfoPath, preg_replace( - '/^const IS_DEVELOPMENT_BUILD = true;$/m', - 'const IS_DEVELOPMENT_BUILD = false;', - $versionInfo -)); echo "please add appropriate notes to the changelog and press enter..."; fgets(STDIN); system('git add "' . dirname(__DIR__) . '/changelogs"'); -system('git commit -m "Release ' . BASE_VERSION . '" --include "' . $versionInfoPath . '"'); -system('git tag ' . BASE_VERSION); -file_put_contents($versionInfoPath, $mod = preg_replace( - $pattern = '/^const BASE_VERSION = "' . preg_quote(BASE_VERSION, '/') . '";$/m', - 'const BASE_VERSION = "' . $nextVer->getBaseVersion() . '";', - $versionInfo -)); +system('git commit -m "Release ' . $currentVer->getBaseVersion() . '" --include "' . $versionInfoPath . '"'); +system('git tag ' . $currentVer->getBaseVersion()); +replaceVersion($versionInfoPath, $nextVer->getBaseVersion(), true); system('git add "' . $versionInfoPath . '"'); system('git commit -m "' . $nextVer->getBaseVersion() . ' is next" --include "' . $versionInfoPath . '"'); echo "pushing changes in 10 seconds\n"; sleep(10); -system('git push origin HEAD ' . BASE_VERSION); +system('git push origin HEAD ' . $currentVer->getBaseVersion()); diff --git a/changelogs/3.8.md b/changelogs/3.8.md index c80432c09..3ab25f02c 100644 --- a/changelogs/3.8.md +++ b/changelogs/3.8.md @@ -63,3 +63,7 @@ This changelog **does not account for protocol changes**. If your plugin uses th - Fixed out-of-bounds access on invalid inventory data in player data saves. - Fixed crash when custom liquids have flow decays which aren't factors of 4. - Fixed `Entity->noDamageTicks` not working when the entity had no previous damage cause. + +# 3.8.7 +- Improved documentation of `Player->getDisplayName()` and `Player::isValidUserName()`. +- Fixed a bug in `SetScorePacket` decoding causing the entry list to always be empty. diff --git a/changelogs/3.9.md b/changelogs/3.9.md new file mode 100644 index 000000000..4fa55b5b8 --- /dev/null +++ b/changelogs/3.9.md @@ -0,0 +1,39 @@ +**For Minecraft: Bedrock Edition 1.12.0** + +### Note about API versions +Plugins which don't touch the protocol and compatible with any previous 3.x.y version will also run on these releases and do not need API bumps. +Plugin developers should **only** update their required API to this version if you need the changes in this build. + +**WARNING: If your plugin uses the protocol, you're not shielded by API change constraints.** You should consider using the `mcpe-protocol` directive in `plugin.yml` as a constraint if you do. + +# 3.9.0 +- Added support for Minecraft: Bedrock Edition 1.12.0 +- Removed compatibility with 1.11.0 + +## Protocol +- The following classes in the `\pocketmine\network\mcpe\protocol` namespace have been renamed: + - `AddEntityPacket` -> `AddActorPacket` + - `AddItemEntityPacket` -> `AddItemActorPacket` + - `AvailableEntityIdentifiersPacket` -> `AvailableActorIdentifiersPacket` + - `BlockEntityDataPacket` -> `BlockActorDataPacket` + - `EntityEventPacket` -> `ActorEventPacket` + - `EntityFallPacket` -> `ActorFallPacket` + - `EntityPickRequestPacket` -> `ActorPickRequestPacket` + - `MoveEntityAbsolutePacket` -> `MoveActorAbsolutePacket` + - `MoveEntityDeltaPacket` -> `MoveActorDeltaPacket` + - `RemoveEntityPacket` -> `RemoveActorPacket` + - `SetEntityDataPacket` -> `SetActorDataPacket` + - `SetEntityLinkPacket` -> `SetActorLinkPacket` + - `SetEntityMotionPacket` -> `SetActorMotionPacket` + - `TakeItemEntityPacket` -> `TakeItemActorPacket` +- The following classes in the `\pocketmine\network\mcpe\protocol` namespace have been removed: + - `FullChunkDataPacket` +- The following classes in the `\pocketmine\network\mcpe\protocol` namespace have been added: + - `AddEntityPacket` (not to be confused with the old one) + - `ClientCacheBlobStatusPacket` + - `ClientCacheMissResponsePacket` + - `ClientCacheStatusPacket` + - `LevelChunkPacket` + - `RemoveEntityPacket` (not to be confused with the old one) + - `StructureTemplateDataExportRequestPacket` + - `StructureTemplateDataExportResponsePacket` diff --git a/resources/vanilla b/resources/vanilla index 6e2aaa6a1..b5a8c68c4 160000 --- a/resources/vanilla +++ b/resources/vanilla @@ -1 +1 @@ -Subproject commit 6e2aaa6a169e3398c338d5bcc197137c2e159d88 +Subproject commit b5a8c68c4262e5d9d7f8280c1d07c252a5e8dbf8 diff --git a/src/pocketmine/block/tile/MonsterSpawner.php b/src/pocketmine/block/tile/MonsterSpawner.php index dba2f2938..601c15e2d 100644 --- a/src/pocketmine/block/tile/MonsterSpawner.php +++ b/src/pocketmine/block/tile/MonsterSpawner.php @@ -27,7 +27,7 @@ use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\IntTag; use pocketmine\nbt\tag\ListTag; use pocketmine\nbt\tag\StringTag; -use pocketmine\network\mcpe\protocol\AddEntityPacket; +use pocketmine\network\mcpe\protocol\AddActorPacket; /** * @deprecated @@ -97,7 +97,7 @@ class MonsterSpawner extends Spawnable{ public function readSaveData(CompoundTag $nbt) : void{ if($nbt->hasTag(self::TAG_LEGACY_ENTITY_TYPE_ID, IntTag::class)){ //TODO: this will cause unexpected results when there's no mapping for the entity - $this->entityTypeId = AddEntityPacket::LEGACY_ID_MAP_BC[$nbt->getInt(self::TAG_LEGACY_ENTITY_TYPE_ID)] ?? ":"; + $this->entityTypeId = AddActorPacket::LEGACY_ID_MAP_BC[$nbt->getInt(self::TAG_LEGACY_ENTITY_TYPE_ID)] ?? ":"; }elseif($nbt->hasTag(self::TAG_ENTITY_TYPE_ID, StringTag::class)){ $this->entityTypeId = $nbt->getString(self::TAG_ENTITY_TYPE_ID); }else{ diff --git a/src/pocketmine/entity/Entity.php b/src/pocketmine/entity/Entity.php index 1deae6a8b..eb4042146 100644 --- a/src/pocketmine/entity/Entity.php +++ b/src/pocketmine/entity/Entity.php @@ -44,18 +44,18 @@ use pocketmine\nbt\tag\DoubleTag; use pocketmine\nbt\tag\FloatTag; use pocketmine\nbt\tag\ListTag; use pocketmine\nbt\tag\StringTag; -use pocketmine\network\mcpe\protocol\AddEntityPacket; use pocketmine\network\mcpe\protocol\AnimatePacket; -use pocketmine\network\mcpe\protocol\EntityEventPacket; -use pocketmine\network\mcpe\protocol\MoveEntityAbsolutePacket; -use pocketmine\network\mcpe\protocol\RemoveEntityPacket; -use pocketmine\network\mcpe\protocol\SetEntityDataPacket; -use pocketmine\network\mcpe\protocol\SetEntityMotionPacket; use pocketmine\network\mcpe\protocol\types\DataPropertyManager; use pocketmine\network\mcpe\protocol\types\EntityMetadataFlags; use pocketmine\network\mcpe\protocol\types\EntityMetadataProperties; use pocketmine\network\mcpe\protocol\types\EntityMetadataTypes; use pocketmine\player\Player; +use pocketmine\network\mcpe\protocol\AddActorPacket; +use pocketmine\network\mcpe\protocol\ActorEventPacket; +use pocketmine\network\mcpe\protocol\MoveActorAbsolutePacket; +use pocketmine\network\mcpe\protocol\RemoveActorPacket; +use pocketmine\network\mcpe\protocol\SetActorDataPacket; +use pocketmine\network\mcpe\protocol\SetActorMotionPacket; use pocketmine\Server; use pocketmine\timings\Timings; use pocketmine\timings\TimingsHandler; @@ -852,7 +852,7 @@ abstract class Entity extends Location implements EntityIds{ } protected function broadcastMovement(bool $teleport = false) : void{ - $pk = new MoveEntityAbsolutePacket(); + $pk = new MoveActorAbsolutePacket(); $pk->entityRuntimeId = $this->id; $pk->position = $this->getOffsetPosition($this); @@ -864,14 +864,14 @@ abstract class Entity extends Location implements EntityIds{ $pk->zRot = $this->yaw; if($teleport){ - $pk->flags |= MoveEntityAbsolutePacket::FLAG_TELEPORT; + $pk->flags |= MoveActorAbsolutePacket::FLAG_TELEPORT; } $this->world->broadcastPacketToViewers($this, $pk); } protected function broadcastMotion() : void{ - $this->world->broadcastPacketToViewers($this, SetEntityMotionPacket::create($this->id, $this->getMotion())); + $this->world->broadcastPacketToViewers($this, SetActorMotionPacket::create($this->id, $this->getMotion())); } public function hasGravity() : bool{ @@ -1592,7 +1592,7 @@ abstract class Entity extends Location implements EntityIds{ * @param Player $player */ protected function sendSpawnPacket(Player $player) : void{ - $pk = new AddEntityPacket(); + $pk = new AddActorPacket(); $pk->entityRuntimeId = $this->getId(); $pk->type = static::NETWORK_ID; $pk->position = $this->asVector3(); @@ -1642,7 +1642,7 @@ abstract class Entity extends Location implements EntityIds{ $id = spl_object_id($player); if(isset($this->hasSpawned[$id])){ if($send){ - $player->sendDataPacket(RemoveEntityPacket::create($this->id)); + $player->sendDataPacket(RemoveActorPacket::create($this->id)); } unset($this->hasSpawned[$id]); } @@ -1769,7 +1769,7 @@ abstract class Entity extends Location implements EntityIds{ $player = [$player]; } - $pk = SetEntityDataPacket::create($this->getId(), $data ?? $this->propertyManager->getAll()); + $pk = SetActorDataPacket::create($this->getId(), $data ?? $this->propertyManager->getAll()); foreach($player as $p){ if($p === $this){ @@ -1784,7 +1784,7 @@ abstract class Entity extends Location implements EntityIds{ } public function broadcastEntityEvent(int $eventId, ?int $eventData = null, ?array $players = null) : void{ - $this->server->broadcastPacket($players ?? $this->getViewers(), EntityEventPacket::create($this->id, $eventId, $eventData ?? 0)); + $this->server->broadcastPacket($players ?? $this->getViewers(), ActorEventPacket::create($this->id, $eventId, $eventData ?? 0)); } public function broadcastAnimation(?array $players, int $animationId) : void{ diff --git a/src/pocketmine/entity/Human.php b/src/pocketmine/entity/Human.php index 5900b78bc..472435348 100644 --- a/src/pocketmine/entity/Human.php +++ b/src/pocketmine/entity/Human.php @@ -41,8 +41,8 @@ use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\IntTag; use pocketmine\nbt\tag\ListTag; use pocketmine\nbt\tag\StringTag; +use pocketmine\network\mcpe\protocol\ActorEventPacket; use pocketmine\network\mcpe\protocol\AddPlayerPacket; -use pocketmine\network\mcpe\protocol\EntityEventPacket; use pocketmine\network\mcpe\protocol\PlayerListPacket; use pocketmine\network\mcpe\protocol\PlayerSkinPacket; use pocketmine\network\mcpe\protocol\types\EntityMetadataProperties; @@ -319,7 +319,7 @@ class Human extends Living implements ProjectileSource, InventoryHolder{ $this->effectManager->add(new EffectInstance(Effect::FIRE_RESISTANCE(), 40 * 20, 1)); $this->effectManager->add(new EffectInstance(Effect::ABSORPTION(), 5 * 20, 1)); - $this->broadcastEntityEvent(EntityEventPacket::CONSUME_TOTEM); + $this->broadcastEntityEvent(ActorEventPacket::CONSUME_TOTEM); $this->world->addSound($this->add(0, $this->eyeHeight, 0), new TotemUseSound()); $hand = $this->inventory->getItemInHand(); diff --git a/src/pocketmine/entity/Living.php b/src/pocketmine/entity/Living.php index 8f41f0900..a8eda7461 100644 --- a/src/pocketmine/entity/Living.php +++ b/src/pocketmine/entity/Living.php @@ -44,7 +44,7 @@ use pocketmine\math\VoxelRayTrace; use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\FloatTag; use pocketmine\nbt\tag\ListTag; -use pocketmine\network\mcpe\protocol\EntityEventPacket; +use pocketmine\network\mcpe\protocol\ActorEventPacket; use pocketmine\network\mcpe\protocol\types\EntityMetadataFlags; use pocketmine\network\mcpe\protocol\types\EntityMetadataProperties; use pocketmine\player\Player; @@ -146,7 +146,7 @@ abstract class Living extends Entity{ parent::setHealth($amount); $this->attributeMap->getAttribute(Attribute::HEALTH)->setValue(ceil($this->getHealth()), true); if($this->isAlive() and !$wasAlive){ - $this->broadcastEntityEvent(EntityEventPacket::RESPAWN); + $this->broadcastEntityEvent(ActorEventPacket::RESPAWN); } } @@ -454,7 +454,7 @@ abstract class Living extends Entity{ } protected function doHitAnimation() : void{ - $this->broadcastEntityEvent(EntityEventPacket::HURT_ANIMATION); + $this->broadcastEntityEvent(ActorEventPacket::HURT_ANIMATION); } public function knockBack(float $x, float $z, float $base = 0.4) : void{ @@ -507,7 +507,7 @@ abstract class Living extends Entity{ } protected function startDeathAnimation() : void{ - $this->broadcastEntityEvent(EntityEventPacket::DEATH_ANIMATION); + $this->broadcastEntityEvent(ActorEventPacket::DEATH_ANIMATION); } protected function endDeathAnimation() : void{ diff --git a/src/pocketmine/entity/Squid.php b/src/pocketmine/entity/Squid.php index 4fb95b268..6db85a373 100644 --- a/src/pocketmine/entity/Squid.php +++ b/src/pocketmine/entity/Squid.php @@ -28,7 +28,7 @@ use pocketmine\event\entity\EntityDamageEvent; use pocketmine\item\VanillaItems; use pocketmine\math\Vector3; use pocketmine\nbt\tag\CompoundTag; -use pocketmine\network\mcpe\protocol\EntityEventPacket; +use pocketmine\network\mcpe\protocol\ActorEventPacket; use function atan2; use function mt_rand; use function sqrt; @@ -68,7 +68,7 @@ class Squid extends WaterAnimal{ $this->swimDirection = (new Vector3($this->x - $e->x, $this->y - $e->y, $this->z - $e->z))->normalize(); } - $this->broadcastEntityEvent(EntityEventPacket::SQUID_INK_CLOUD); + $this->broadcastEntityEvent(ActorEventPacket::SQUID_INK_CLOUD); } } diff --git a/src/pocketmine/entity/object/ItemEntity.php b/src/pocketmine/entity/object/ItemEntity.php index fcb5727ff..dcf250aef 100644 --- a/src/pocketmine/entity/object/ItemEntity.php +++ b/src/pocketmine/entity/object/ItemEntity.php @@ -31,9 +31,9 @@ use pocketmine\event\inventory\InventoryPickupItemEvent; use pocketmine\item\Item; use pocketmine\item\ItemIds; use pocketmine\nbt\tag\CompoundTag; -use pocketmine\network\mcpe\protocol\AddItemEntityPacket; -use pocketmine\network\mcpe\protocol\TakeItemEntityPacket; use pocketmine\player\Player; +use pocketmine\network\mcpe\protocol\AddItemActorPacket; +use pocketmine\network\mcpe\protocol\TakeItemActorPacket; use function get_class; use function max; @@ -234,7 +234,7 @@ class ItemEntity extends Entity{ } protected function sendSpawnPacket(Player $player) : void{ - $pk = new AddItemEntityPacket(); + $pk = new AddItemActorPacket(); $pk->entityRuntimeId = $this->getId(); $pk->position = $this->asVector3(); $pk->motion = $this->getMotion(); @@ -268,7 +268,7 @@ class ItemEntity extends Entity{ $player->awardAchievement("diamond"); } - $this->server->broadcastPacket($this->getViewers(), TakeItemEntityPacket::create($player->getId(), $this->getId())); + $this->server->broadcastPacket($this->getViewers(), TakeItemActorPacket::create($player->getId(), $this->getId())); $playerInventory->addItem(clone $item); $this->flagForDespawn(); diff --git a/src/pocketmine/entity/object/Painting.php b/src/pocketmine/entity/object/Painting.php index 0f734a4c1..ae8118350 100644 --- a/src/pocketmine/entity/object/Painting.php +++ b/src/pocketmine/entity/object/Painting.php @@ -140,9 +140,11 @@ class Painting extends Entity{ protected function sendSpawnPacket(Player $player) : void{ $pk = new AddPaintingPacket(); $pk->entityRuntimeId = $this->getId(); - $pk->x = $this->blockIn->x; - $pk->y = $this->blockIn->y; - $pk->z = $this->blockIn->z; + $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 = $this->direction; $pk->title = $this->motive; diff --git a/src/pocketmine/entity/projectile/Arrow.php b/src/pocketmine/entity/projectile/Arrow.php index b9c55dc79..51926dc4f 100644 --- a/src/pocketmine/entity/projectile/Arrow.php +++ b/src/pocketmine/entity/projectile/Arrow.php @@ -30,8 +30,8 @@ use pocketmine\event\inventory\InventoryPickupArrowEvent; use pocketmine\item\VanillaItems; use pocketmine\math\RayTraceResult; use pocketmine\nbt\tag\CompoundTag; -use pocketmine\network\mcpe\protocol\EntityEventPacket; -use pocketmine\network\mcpe\protocol\TakeItemEntityPacket; +use pocketmine\network\mcpe\protocol\ActorEventPacket; +use pocketmine\network\mcpe\protocol\TakeItemActorPacket; use pocketmine\network\mcpe\protocol\types\EntityMetadataFlags; use pocketmine\player\Player; use pocketmine\world\sound\ArrowHitSound; @@ -143,7 +143,7 @@ class Arrow extends Projectile{ protected function onHitBlock(Block $blockHit, RayTraceResult $hitResult) : void{ parent::onHitBlock($blockHit, $hitResult); - $this->broadcastEntityEvent(EntityEventPacket::ARROW_SHAKE, 7); //7 ticks + $this->broadcastEntityEvent(ActorEventPacket::ARROW_SHAKE, 7); //7 ticks } protected function onHitEntity(Entity $entityHit, RayTraceResult $hitResult) : void{ @@ -193,7 +193,7 @@ class Arrow extends Projectile{ return; } - $this->server->broadcastPacket($this->getViewers(), TakeItemEntityPacket::create($player->getId(), $this->getId())); + $this->server->broadcastPacket($this->getViewers(), TakeItemActorPacket::create($player->getId(), $this->getId())); $playerInventory->addItem(clone $item); $this->flagForDespawn(); diff --git a/src/pocketmine/network/mcpe/ChunkRequestTask.php b/src/pocketmine/network/mcpe/ChunkRequestTask.php index 9c31d7e16..1ac04e511 100644 --- a/src/pocketmine/network/mcpe/ChunkRequestTask.php +++ b/src/pocketmine/network/mcpe/ChunkRequestTask.php @@ -25,7 +25,7 @@ namespace pocketmine\network\mcpe; use pocketmine\network\mcpe\compression\CompressBatchPromise; use pocketmine\network\mcpe\compression\Zlib; -use pocketmine\network\mcpe\protocol\FullChunkDataPacket; +use pocketmine\network\mcpe\protocol\LevelChunkPacket; use pocketmine\network\mcpe\serializer\ChunkSerializer; use pocketmine\scheduler\AsyncTask; use pocketmine\world\format\Chunk; @@ -60,8 +60,10 @@ class ChunkRequestTask extends AsyncTask{ } public function onRun() : void{ - $chunk = ChunkSerializer::serialize(FastChunkSerializer::deserialize($this->chunk), $this->tiles); - $this->setResult(Zlib::compress(PacketBatch::fromPackets(FullChunkDataPacket::create($this->chunkX, $this->chunkZ, $chunk))->getBuffer(), $this->compressionLevel)); + $chunk = FastChunkSerializer::deserialize($this->chunk); + $subCount = $chunk->getSubChunkSendCount(); + $payload = ChunkSerializer::serialize($chunk, $this->tiles); + $this->setResult(Zlib::compress(PacketBatch::fromPackets(LevelChunkPacket::withoutCache($this->chunkX, $this->chunkZ, $subCount, $payload))->getBuffer(), $this->compressionLevel)); } public function onError() : void{ diff --git a/src/pocketmine/network/mcpe/handler/InGamePacketHandler.php b/src/pocketmine/network/mcpe/handler/InGamePacketHandler.php index 3ef0dc519..dca96ce6d 100644 --- a/src/pocketmine/network/mcpe/handler/InGamePacketHandler.php +++ b/src/pocketmine/network/mcpe/handler/InGamePacketHandler.php @@ -39,9 +39,12 @@ use pocketmine\nbt\NbtDataException; use pocketmine\nbt\tag\StringTag; use pocketmine\network\BadPacketException; use pocketmine\network\mcpe\NetworkSession; +use pocketmine\network\mcpe\protocol\ActorEventPacket; +use pocketmine\network\mcpe\protocol\ActorFallPacket; +use pocketmine\network\mcpe\protocol\ActorPickRequestPacket; use pocketmine\network\mcpe\protocol\AdventureSettingsPacket; use pocketmine\network\mcpe\protocol\AnimatePacket; -use pocketmine\network\mcpe\protocol\BlockEntityDataPacket; +use pocketmine\network\mcpe\protocol\BlockActorDataPacket; use pocketmine\network\mcpe\protocol\BlockPickRequestPacket; use pocketmine\network\mcpe\protocol\BookEditPacket; use pocketmine\network\mcpe\protocol\BossEventPacket; @@ -49,9 +52,6 @@ use pocketmine\network\mcpe\protocol\CommandBlockUpdatePacket; use pocketmine\network\mcpe\protocol\CommandRequestPacket; use pocketmine\network\mcpe\protocol\ContainerClosePacket; use pocketmine\network\mcpe\protocol\CraftingEventPacket; -use pocketmine\network\mcpe\protocol\EntityEventPacket; -use pocketmine\network\mcpe\protocol\EntityFallPacket; -use pocketmine\network\mcpe\protocol\EntityPickRequestPacket; use pocketmine\network\mcpe\protocol\InteractPacket; use pocketmine\network\mcpe\protocol\InventoryTransactionPacket; use pocketmine\network\mcpe\protocol\ItemFrameDropItemPacket; @@ -143,16 +143,16 @@ class InGamePacketHandler extends PacketHandler{ return true; //useless leftover from 1.8 } - public function handleEntityEvent(EntityEventPacket $packet) : bool{ + public function handleActorEvent(ActorEventPacket $packet) : bool{ $this->player->doCloseInventory(); switch($packet->event){ - case EntityEventPacket::EATING_ITEM: //TODO: ignore this and handle it server-side + case ActorEventPacket::EATING_ITEM: //TODO: ignore this and handle it server-side if($packet->data === 0){ return false; } - $this->player->broadcastEntityEvent(EntityEventPacket::EATING_ITEM, $packet->data); + $this->player->broadcastEntityEvent(ActorEventPacket::EATING_ITEM, $packet->data); break; default: return false; @@ -385,7 +385,7 @@ class InGamePacketHandler extends PacketHandler{ return $this->player->pickBlock(new Vector3($packet->blockX, $packet->blockY, $packet->blockZ), $packet->addUserData); } - public function handleEntityPickRequest(EntityPickRequestPacket $packet) : bool{ + public function handleActorPickRequest(ActorPickRequestPacket $packet) : bool{ return false; //TODO } @@ -454,7 +454,7 @@ class InGamePacketHandler extends PacketHandler{ return true; } - public function handleEntityFall(EntityFallPacket $packet) : bool{ + public function handleActorFall(ActorFallPacket $packet) : bool{ return true; //Not used } @@ -508,7 +508,7 @@ class InGamePacketHandler extends PacketHandler{ return $handled; } - public function handleBlockEntityData(BlockEntityDataPacket $packet) : bool{ + public function handleBlockActorData(BlockActorDataPacket $packet) : bool{ $pos = new Vector3($packet->x, $packet->y, $packet->z); if($pos->distanceSquared($this->player) > 10000){ return false; diff --git a/src/pocketmine/network/mcpe/handler/PacketHandler.php b/src/pocketmine/network/mcpe/handler/PacketHandler.php index a552d7329..ee0a4aad2 100644 --- a/src/pocketmine/network/mcpe/handler/PacketHandler.php +++ b/src/pocketmine/network/mcpe/handler/PacketHandler.php @@ -23,18 +23,22 @@ declare(strict_types=1); namespace pocketmine\network\mcpe\handler; +use pocketmine\network\mcpe\protocol\ActorEventPacket; +use pocketmine\network\mcpe\protocol\ActorFallPacket; +use pocketmine\network\mcpe\protocol\ActorPickRequestPacket; +use pocketmine\network\mcpe\protocol\AddActorPacket; use pocketmine\network\mcpe\protocol\AddBehaviorTreePacket; use pocketmine\network\mcpe\protocol\AddEntityPacket; -use pocketmine\network\mcpe\protocol\AddItemEntityPacket; +use pocketmine\network\mcpe\protocol\AddItemActorPacket; use pocketmine\network\mcpe\protocol\AddPaintingPacket; use pocketmine\network\mcpe\protocol\AddPlayerPacket; use pocketmine\network\mcpe\protocol\AdventureSettingsPacket; use pocketmine\network\mcpe\protocol\AnimatePacket; use pocketmine\network\mcpe\protocol\AutomationClientConnectPacket; +use pocketmine\network\mcpe\protocol\AvailableActorIdentifiersPacket; use pocketmine\network\mcpe\protocol\AvailableCommandsPacket; -use pocketmine\network\mcpe\protocol\AvailableEntityIdentifiersPacket; use pocketmine\network\mcpe\protocol\BiomeDefinitionListPacket; -use pocketmine\network\mcpe\protocol\BlockEntityDataPacket; +use pocketmine\network\mcpe\protocol\BlockActorDataPacket; use pocketmine\network\mcpe\protocol\BlockEventPacket; use pocketmine\network\mcpe\protocol\BlockPickRequestPacket; use pocketmine\network\mcpe\protocol\BookEditPacket; @@ -43,6 +47,9 @@ use pocketmine\network\mcpe\protocol\CameraPacket; use pocketmine\network\mcpe\protocol\ChangeDimensionPacket; use pocketmine\network\mcpe\protocol\ChunkRadiusUpdatedPacket; use pocketmine\network\mcpe\protocol\ClientboundMapItemDataPacket; +use pocketmine\network\mcpe\protocol\ClientCacheBlobStatusPacket; +use pocketmine\network\mcpe\protocol\ClientCacheMissResponsePacket; +use pocketmine\network\mcpe\protocol\ClientCacheStatusPacket; use pocketmine\network\mcpe\protocol\ClientToServerHandshakePacket; use pocketmine\network\mcpe\protocol\CommandBlockUpdatePacket; use pocketmine\network\mcpe\protocol\CommandOutputPacket; @@ -53,12 +60,8 @@ use pocketmine\network\mcpe\protocol\ContainerSetDataPacket; use pocketmine\network\mcpe\protocol\CraftingDataPacket; use pocketmine\network\mcpe\protocol\CraftingEventPacket; use pocketmine\network\mcpe\protocol\DisconnectPacket; -use pocketmine\network\mcpe\protocol\EntityEventPacket; -use pocketmine\network\mcpe\protocol\EntityFallPacket; -use pocketmine\network\mcpe\protocol\EntityPickRequestPacket; use pocketmine\network\mcpe\protocol\EventPacket; use pocketmine\network\mcpe\protocol\ExplodePacket; -use pocketmine\network\mcpe\protocol\FullChunkDataPacket; use pocketmine\network\mcpe\protocol\GameRulesChangedPacket; use pocketmine\network\mcpe\protocol\GuiDataPickItemPacket; use pocketmine\network\mcpe\protocol\HurtArmorPacket; @@ -69,6 +72,8 @@ use pocketmine\network\mcpe\protocol\InventoryTransactionPacket; use pocketmine\network\mcpe\protocol\ItemFrameDropItemPacket; use pocketmine\network\mcpe\protocol\LabTablePacket; use pocketmine\network\mcpe\protocol\LecternUpdatePacket; +use pocketmine\network\mcpe\protocol\LevelChunkPacket; +use pocketmine\network\mcpe\protocol\LevelEventGenericPacket; use pocketmine\network\mcpe\protocol\LevelEventPacket; use pocketmine\network\mcpe\protocol\LevelSoundEventPacket; use pocketmine\network\mcpe\protocol\LevelSoundEventPacketV1; @@ -81,8 +86,8 @@ use pocketmine\network\mcpe\protocol\MobEffectPacket; use pocketmine\network\mcpe\protocol\MobEquipmentPacket; use pocketmine\network\mcpe\protocol\ModalFormRequestPacket; use pocketmine\network\mcpe\protocol\ModalFormResponsePacket; -use pocketmine\network\mcpe\protocol\MoveEntityAbsolutePacket; -use pocketmine\network\mcpe\protocol\MoveEntityDeltaPacket; +use pocketmine\network\mcpe\protocol\MoveActorAbsolutePacket; +use pocketmine\network\mcpe\protocol\MoveActorDeltaPacket; use pocketmine\network\mcpe\protocol\MovePlayerPacket; use pocketmine\network\mcpe\protocol\NetworkChunkPublisherUpdatePacket; use pocketmine\network\mcpe\protocol\NetworkStackLatencyPacket; @@ -97,6 +102,7 @@ use pocketmine\network\mcpe\protocol\PlayerSkinPacket; use pocketmine\network\mcpe\protocol\PlaySoundPacket; use pocketmine\network\mcpe\protocol\PlayStatusPacket; use pocketmine\network\mcpe\protocol\PurchaseReceiptPacket; +use pocketmine\network\mcpe\protocol\RemoveActorPacket; use pocketmine\network\mcpe\protocol\RemoveEntityPacket; use pocketmine\network\mcpe\protocol\RemoveObjectivePacket; use pocketmine\network\mcpe\protocol\RequestChunkRadiusPacket; @@ -112,13 +118,13 @@ use pocketmine\network\mcpe\protocol\ScriptCustomEventPacket; use pocketmine\network\mcpe\protocol\ServerSettingsRequestPacket; use pocketmine\network\mcpe\protocol\ServerSettingsResponsePacket; use pocketmine\network\mcpe\protocol\ServerToClientHandshakePacket; +use pocketmine\network\mcpe\protocol\SetActorDataPacket; +use pocketmine\network\mcpe\protocol\SetActorLinkPacket; +use pocketmine\network\mcpe\protocol\SetActorMotionPacket; use pocketmine\network\mcpe\protocol\SetCommandsEnabledPacket; use pocketmine\network\mcpe\protocol\SetDefaultGameTypePacket; use pocketmine\network\mcpe\protocol\SetDifficultyPacket; use pocketmine\network\mcpe\protocol\SetDisplayObjectivePacket; -use pocketmine\network\mcpe\protocol\SetEntityDataPacket; -use pocketmine\network\mcpe\protocol\SetEntityLinkPacket; -use pocketmine\network\mcpe\protocol\SetEntityMotionPacket; use pocketmine\network\mcpe\protocol\SetHealthPacket; use pocketmine\network\mcpe\protocol\SetLastHurtByPacket; use pocketmine\network\mcpe\protocol\SetLocalPlayerAsInitializedPacket; @@ -137,12 +143,15 @@ use pocketmine\network\mcpe\protocol\SpawnParticleEffectPacket; use pocketmine\network\mcpe\protocol\StartGamePacket; use pocketmine\network\mcpe\protocol\StopSoundPacket; use pocketmine\network\mcpe\protocol\StructureBlockUpdatePacket; +use pocketmine\network\mcpe\protocol\StructureTemplateDataExportRequestPacket; +use pocketmine\network\mcpe\protocol\StructureTemplateDataExportResponsePacket; use pocketmine\network\mcpe\protocol\SubClientLoginPacket; -use pocketmine\network\mcpe\protocol\TakeItemEntityPacket; +use pocketmine\network\mcpe\protocol\TakeItemActorPacket; use pocketmine\network\mcpe\protocol\TextPacket; use pocketmine\network\mcpe\protocol\TransferPacket; use pocketmine\network\mcpe\protocol\UpdateAttributesPacket; use pocketmine\network\mcpe\protocol\UpdateBlockPacket; +use pocketmine\network\mcpe\protocol\UpdateBlockPropertiesPacket; use pocketmine\network\mcpe\protocol\UpdateBlockSyncedPacket; use pocketmine\network\mcpe\protocol\UpdateEquipPacket; use pocketmine\network\mcpe\protocol\UpdateSoftEnumPacket; @@ -209,23 +218,23 @@ abstract class PacketHandler{ return false; } - public function handleAddEntity(AddEntityPacket $packet) : bool{ + public function handleAddActor(AddActorPacket $packet) : bool{ return false; } - public function handleRemoveEntity(RemoveEntityPacket $packet) : bool{ + public function handleRemoveActor(RemoveActorPacket $packet) : bool{ return false; } - public function handleAddItemEntity(AddItemEntityPacket $packet) : bool{ + public function handleAddItemActor(AddItemActorPacket $packet) : bool{ return false; } - public function handleTakeItemEntity(TakeItemEntityPacket $packet) : bool{ + public function handleTakeItemActor(TakeItemActorPacket $packet) : bool{ return false; } - public function handleMoveEntityAbsolute(MoveEntityAbsolutePacket $packet) : bool{ + public function handleMoveActorAbsolute(MoveActorAbsolutePacket $packet) : bool{ return false; } @@ -261,7 +270,7 @@ abstract class PacketHandler{ return false; } - public function handleEntityEvent(EntityEventPacket $packet) : bool{ + public function handleActorEvent(ActorEventPacket $packet) : bool{ return false; } @@ -293,7 +302,7 @@ abstract class PacketHandler{ return false; } - public function handleEntityPickRequest(EntityPickRequestPacket $packet) : bool{ + public function handleActorPickRequest(ActorPickRequestPacket $packet) : bool{ return false; } @@ -301,7 +310,7 @@ abstract class PacketHandler{ return false; } - public function handleEntityFall(EntityFallPacket $packet) : bool{ + public function handleActorFall(ActorFallPacket $packet) : bool{ return false; } @@ -309,15 +318,15 @@ abstract class PacketHandler{ return false; } - public function handleSetEntityData(SetEntityDataPacket $packet) : bool{ + public function handleSetActorData(SetActorDataPacket $packet) : bool{ return false; } - public function handleSetEntityMotion(SetEntityMotionPacket $packet) : bool{ + public function handleSetActorMotion(SetActorMotionPacket $packet) : bool{ return false; } - public function handleSetEntityLink(SetEntityLinkPacket $packet) : bool{ + public function handleSetActorLink(SetActorLinkPacket $packet) : bool{ return false; } @@ -377,7 +386,7 @@ abstract class PacketHandler{ return false; } - public function handleBlockEntityData(BlockEntityDataPacket $packet) : bool{ + public function handleBlockActorData(BlockActorDataPacket $packet) : bool{ return false; } @@ -385,7 +394,7 @@ abstract class PacketHandler{ return false; } - public function handleFullChunkData(FullChunkDataPacket $packet) : bool{ + public function handleLevelChunk(LevelChunkPacket $packet) : bool{ return false; } @@ -597,7 +606,7 @@ abstract class PacketHandler{ return false; } - public function handleMoveEntityDelta(MoveEntityDeltaPacket $packet) : bool{ + public function handleMoveActorDelta(MoveActorDeltaPacket $packet) : bool{ return false; } @@ -625,7 +634,7 @@ abstract class PacketHandler{ return false; } - public function handleAvailableEntityIdentifiers(AvailableEntityIdentifiersPacket $packet) : bool{ + public function handleAvailableActorIdentifiers(AvailableActorIdentifiersPacket $packet) : bool{ return false; } @@ -645,6 +654,10 @@ abstract class PacketHandler{ return false; } + public function handleLevelEventGeneric(LevelEventGenericPacket $packet) : bool{ + return false; + } + public function handleLecternUpdate(LecternUpdatePacket $packet) : bool{ return false; } @@ -653,11 +666,43 @@ abstract class PacketHandler{ return false; } - public function handleMapCreateLockedCopy(MapCreateLockedCopyPacket $packet) : bool{ + public function handleAddEntity(AddEntityPacket $packet) : bool{ + return false; + } + + public function handleRemoveEntity(RemoveEntityPacket $packet) : bool{ + return false; + } + + public function handleClientCacheStatus(ClientCacheStatusPacket $packet) : bool{ return false; } public function handleOnScreenTextureAnimation(OnScreenTextureAnimationPacket $packet) : bool{ return false; } + + public function handleMapCreateLockedCopy(MapCreateLockedCopyPacket $packet) : bool{ + return false; + } + + public function handleStructureTemplateDataExportRequest(StructureTemplateDataExportRequestPacket $packet) : bool{ + return false; + } + + public function handleStructureTemplateDataExportResponse(StructureTemplateDataExportResponsePacket $packet) : bool{ + return false; + } + + public function handleUpdateBlockProperties(UpdateBlockPropertiesPacket $packet) : bool{ + return false; + } + + public function handleClientCacheBlobStatus(ClientCacheBlobStatusPacket $packet) : bool{ + return false; + } + + public function handleClientCacheMissResponse(ClientCacheMissResponsePacket $packet) : bool{ + return false; + } } diff --git a/src/pocketmine/network/mcpe/handler/PreSpawnPacketHandler.php b/src/pocketmine/network/mcpe/handler/PreSpawnPacketHandler.php index 066a37b36..b643f00d9 100644 --- a/src/pocketmine/network/mcpe/handler/PreSpawnPacketHandler.php +++ b/src/pocketmine/network/mcpe/handler/PreSpawnPacketHandler.php @@ -24,7 +24,7 @@ declare(strict_types=1); namespace pocketmine\network\mcpe\handler; use pocketmine\network\mcpe\NetworkSession; -use pocketmine\network\mcpe\protocol\AvailableEntityIdentifiersPacket; +use pocketmine\network\mcpe\protocol\AvailableActorIdentifiersPacket; use pocketmine\network\mcpe\protocol\BiomeDefinitionListPacket; use pocketmine\network\mcpe\protocol\RequestChunkRadiusPacket; use pocketmine\network\mcpe\protocol\SetLocalPlayerAsInitializedPacket; @@ -78,7 +78,7 @@ class PreSpawnPacketHandler extends PacketHandler{ $pk->worldName = $this->server->getMotd(); $this->session->sendDataPacket($pk); - $this->session->sendDataPacket(new AvailableEntityIdentifiersPacket()); + $this->session->sendDataPacket(new AvailableActorIdentifiersPacket()); $this->session->sendDataPacket(new BiomeDefinitionListPacket()); $this->player->setImmobile(); //HACK: fix client-side falling pre-spawn diff --git a/src/pocketmine/network/mcpe/protocol/EntityEventPacket.php b/src/pocketmine/network/mcpe/protocol/ActorEventPacket.php similarity index 94% rename from src/pocketmine/network/mcpe/protocol/EntityEventPacket.php rename to src/pocketmine/network/mcpe/protocol/ActorEventPacket.php index 6e84401af..ae459f8cd 100644 --- a/src/pocketmine/network/mcpe/protocol/EntityEventPacket.php +++ b/src/pocketmine/network/mcpe/protocol/ActorEventPacket.php @@ -25,11 +25,10 @@ namespace pocketmine\network\mcpe\protocol; #include - use pocketmine\network\mcpe\handler\PacketHandler; -class EntityEventPacket extends DataPacket implements ClientboundPacket, ServerboundPacket{ - public const NETWORK_ID = ProtocolInfo::ENTITY_EVENT_PACKET; +class ActorEventPacket extends DataPacket implements ClientboundPacket, ServerboundPacket{ + public const NETWORK_ID = ProtocolInfo::ACTOR_EVENT_PACKET; public const HURT_ANIMATION = 2; public const DEATH_ANIMATION = 3; @@ -111,6 +110,6 @@ class EntityEventPacket extends DataPacket implements ClientboundPacket, Serverb } public function handle(PacketHandler $handler) : bool{ - return $handler->handleEntityEvent($this); + return $handler->handleActorEvent($this); } } diff --git a/src/pocketmine/network/mcpe/protocol/EntityFallPacket.php b/src/pocketmine/network/mcpe/protocol/ActorFallPacket.php similarity index 88% rename from src/pocketmine/network/mcpe/protocol/EntityFallPacket.php rename to src/pocketmine/network/mcpe/protocol/ActorFallPacket.php index d457d56c0..ab2d59fcb 100644 --- a/src/pocketmine/network/mcpe/protocol/EntityFallPacket.php +++ b/src/pocketmine/network/mcpe/protocol/ActorFallPacket.php @@ -28,8 +28,8 @@ namespace pocketmine\network\mcpe\protocol; use pocketmine\network\mcpe\handler\PacketHandler; -class EntityFallPacket extends DataPacket implements ServerboundPacket{ - public const NETWORK_ID = ProtocolInfo::ENTITY_FALL_PACKET; +class ActorFallPacket extends DataPacket implements ServerboundPacket{ + public const NETWORK_ID = ProtocolInfo::ACTOR_FALL_PACKET; /** @var int */ public $entityRuntimeId; @@ -51,6 +51,6 @@ class EntityFallPacket extends DataPacket implements ServerboundPacket{ } public function handle(PacketHandler $handler) : bool{ - return $handler->handleEntityFall($this); + return $handler->handleActorFall($this); } } diff --git a/src/pocketmine/network/mcpe/protocol/EntityPickRequestPacket.php b/src/pocketmine/network/mcpe/protocol/ActorPickRequestPacket.php similarity index 86% rename from src/pocketmine/network/mcpe/protocol/EntityPickRequestPacket.php rename to src/pocketmine/network/mcpe/protocol/ActorPickRequestPacket.php index 8e43cd30a..6022ea703 100644 --- a/src/pocketmine/network/mcpe/protocol/EntityPickRequestPacket.php +++ b/src/pocketmine/network/mcpe/protocol/ActorPickRequestPacket.php @@ -27,8 +27,8 @@ namespace pocketmine\network\mcpe\protocol; use pocketmine\network\mcpe\handler\PacketHandler; -class EntityPickRequestPacket extends DataPacket implements ServerboundPacket{ - public const NETWORK_ID = ProtocolInfo::ENTITY_PICK_REQUEST_PACKET; +class ActorPickRequestPacket extends DataPacket implements ServerboundPacket{ + public const NETWORK_ID = ProtocolInfo::ACTOR_PICK_REQUEST_PACKET; /** @var int */ public $entityUniqueId; @@ -46,6 +46,6 @@ class EntityPickRequestPacket extends DataPacket implements ServerboundPacket{ } public function handle(PacketHandler $handler) : bool{ - return $handler->handleEntityPickRequest($this); + return $handler->handleActorPickRequest($this); } } diff --git a/src/pocketmine/network/mcpe/protocol/AddActorPacket.php b/src/pocketmine/network/mcpe/protocol/AddActorPacket.php new file mode 100644 index 000000000..c97a93590 --- /dev/null +++ b/src/pocketmine/network/mcpe/protocol/AddActorPacket.php @@ -0,0 +1,245 @@ + + +use pocketmine\entity\Attribute; +use pocketmine\entity\EntityIds; +use pocketmine\math\Vector3; +use pocketmine\network\BadPacketException; +use pocketmine\network\mcpe\handler\PacketHandler; +use pocketmine\network\mcpe\protocol\types\EntityLink; +use function array_search; +use function count; + +class AddActorPacket extends DataPacket implements ClientboundPacket{ + public const NETWORK_ID = ProtocolInfo::ADD_ENTITY_PACKET; + + /* + * Really really really really really nasty hack, to preserve backwards compatibility. + * We can't transition to string IDs within 3.x because the network IDs (the integer ones) are exposed + * to the API in some places (for god's sake shoghi). + * + * TODO: remove this on 4.0 + */ + public const LEGACY_ID_MAP_BC = [ + EntityIds::NPC => "minecraft:npc", + EntityIds::PLAYER => "minecraft:player", + EntityIds::WITHER_SKELETON => "minecraft:wither_skeleton", + EntityIds::HUSK => "minecraft:husk", + EntityIds::STRAY => "minecraft:stray", + EntityIds::WITCH => "minecraft:witch", + EntityIds::ZOMBIE_VILLAGER => "minecraft:zombie_villager", + EntityIds::BLAZE => "minecraft:blaze", + EntityIds::MAGMA_CUBE => "minecraft:magma_cube", + EntityIds::GHAST => "minecraft:ghast", + EntityIds::CAVE_SPIDER => "minecraft:cave_spider", + EntityIds::SILVERFISH => "minecraft:silverfish", + EntityIds::ENDERMAN => "minecraft:enderman", + EntityIds::SLIME => "minecraft:slime", + EntityIds::ZOMBIE_PIGMAN => "minecraft:zombie_pigman", + EntityIds::SPIDER => "minecraft:spider", + EntityIds::SKELETON => "minecraft:skeleton", + EntityIds::CREEPER => "minecraft:creeper", + EntityIds::ZOMBIE => "minecraft:zombie", + EntityIds::SKELETON_HORSE => "minecraft:skeleton_horse", + EntityIds::MULE => "minecraft:mule", + EntityIds::DONKEY => "minecraft:donkey", + EntityIds::DOLPHIN => "minecraft:dolphin", + EntityIds::TROPICALFISH => "minecraft:tropicalfish", + EntityIds::WOLF => "minecraft:wolf", + EntityIds::SQUID => "minecraft:squid", + EntityIds::DROWNED => "minecraft:drowned", + EntityIds::SHEEP => "minecraft:sheep", + EntityIds::MOOSHROOM => "minecraft:mooshroom", + EntityIds::PANDA => "minecraft:panda", + EntityIds::SALMON => "minecraft:salmon", + EntityIds::PIG => "minecraft:pig", + EntityIds::VILLAGER => "minecraft:villager", + EntityIds::COD => "minecraft:cod", + EntityIds::PUFFERFISH => "minecraft:pufferfish", + EntityIds::COW => "minecraft:cow", + EntityIds::CHICKEN => "minecraft:chicken", + EntityIds::BALLOON => "minecraft:balloon", + EntityIds::LLAMA => "minecraft:llama", + EntityIds::IRON_GOLEM => "minecraft:iron_golem", + EntityIds::RABBIT => "minecraft:rabbit", + EntityIds::SNOW_GOLEM => "minecraft:snow_golem", + EntityIds::BAT => "minecraft:bat", + EntityIds::OCELOT => "minecraft:ocelot", + EntityIds::HORSE => "minecraft:horse", + EntityIds::CAT => "minecraft:cat", + EntityIds::POLAR_BEAR => "minecraft:polar_bear", + EntityIds::ZOMBIE_HORSE => "minecraft:zombie_horse", + EntityIds::TURTLE => "minecraft:turtle", + EntityIds::PARROT => "minecraft:parrot", + EntityIds::GUARDIAN => "minecraft:guardian", + EntityIds::ELDER_GUARDIAN => "minecraft:elder_guardian", + EntityIds::VINDICATOR => "minecraft:vindicator", + EntityIds::WITHER => "minecraft:wither", + EntityIds::ENDER_DRAGON => "minecraft:ender_dragon", + EntityIds::SHULKER => "minecraft:shulker", + EntityIds::ENDERMITE => "minecraft:endermite", + EntityIds::MINECART => "minecraft:minecart", + EntityIds::HOPPER_MINECART => "minecraft:hopper_minecart", + EntityIds::TNT_MINECART => "minecraft:tnt_minecart", + EntityIds::CHEST_MINECART => "minecraft:chest_minecart", + EntityIds::COMMAND_BLOCK_MINECART => "minecraft:command_block_minecart", + EntityIds::ARMOR_STAND => "minecraft:armor_stand", + EntityIds::ITEM => "minecraft:item", + EntityIds::TNT => "minecraft:tnt", + EntityIds::FALLING_BLOCK => "minecraft:falling_block", + EntityIds::XP_BOTTLE => "minecraft:xp_bottle", + EntityIds::XP_ORB => "minecraft:xp_orb", + EntityIds::EYE_OF_ENDER_SIGNAL => "minecraft:eye_of_ender_signal", + EntityIds::ENDER_CRYSTAL => "minecraft:ender_crystal", + EntityIds::SHULKER_BULLET => "minecraft:shulker_bullet", + EntityIds::FISHING_HOOK => "minecraft:fishing_hook", + EntityIds::DRAGON_FIREBALL => "minecraft:dragon_fireball", + EntityIds::ARROW => "minecraft:arrow", + EntityIds::SNOWBALL => "minecraft:snowball", + EntityIds::EGG => "minecraft:egg", + EntityIds::PAINTING => "minecraft:painting", + EntityIds::THROWN_TRIDENT => "minecraft:thrown_trident", + EntityIds::FIREBALL => "minecraft:fireball", + EntityIds::SPLASH_POTION => "minecraft:splash_potion", + EntityIds::ENDER_PEARL => "minecraft:ender_pearl", + EntityIds::LEASH_KNOT => "minecraft:leash_knot", + EntityIds::WITHER_SKULL => "minecraft:wither_skull", + EntityIds::WITHER_SKULL_DANGEROUS => "minecraft:wither_skull_dangerous", + EntityIds::BOAT => "minecraft:boat", + EntityIds::LIGHTNING_BOLT => "minecraft:lightning_bolt", + EntityIds::SMALL_FIREBALL => "minecraft:small_fireball", + EntityIds::LLAMA_SPIT => "minecraft:llama_spit", + EntityIds::AREA_EFFECT_CLOUD => "minecraft:area_effect_cloud", + EntityIds::LINGERING_POTION => "minecraft:lingering_potion", + EntityIds::FIREWORKS_ROCKET => "minecraft:fireworks_rocket", + EntityIds::EVOCATION_FANG => "minecraft:evocation_fang", + EntityIds::EVOCATION_ILLAGER => "minecraft:evocation_illager", + EntityIds::VEX => "minecraft:vex", + EntityIds::AGENT => "minecraft:agent", + EntityIds::ICE_BOMB => "minecraft:ice_bomb", + EntityIds::PHANTOM => "minecraft:phantom", + EntityIds::TRIPOD_CAMERA => "minecraft:tripod_camera" + ]; + + /** @var int|null */ + public $entityUniqueId = null; //TODO + /** @var int */ + public $entityRuntimeId; + /** @var int */ + public $type; + /** @var Vector3 */ + public $position; + /** @var Vector3|null */ + public $motion; + /** @var float */ + public $pitch = 0.0; + /** @var float */ + public $yaw = 0.0; + /** @var float */ + public $headYaw = 0.0; + + /** @var Attribute[] */ + public $attributes = []; + /** @var array */ + public $metadata = []; + /** @var EntityLink[] */ + public $links = []; + + protected function decodePayload() : void{ + $this->entityUniqueId = $this->getEntityUniqueId(); + $this->entityRuntimeId = $this->getEntityRuntimeId(); + $this->type = array_search($t = $this->getString(), self::LEGACY_ID_MAP_BC, true); + if($this->type === false){ + throw new BadPacketException("Can't map ID $t to legacy ID"); + } + $this->position = $this->getVector3(); + $this->motion = $this->getVector3(); + $this->pitch = $this->getLFloat(); + $this->yaw = $this->getLFloat(); + $this->headYaw = $this->getLFloat(); + + $attrCount = $this->getUnsignedVarInt(); + for($i = 0; $i < $attrCount; ++$i){ + $id = $this->getString(); + $min = $this->getLFloat(); + $current = $this->getLFloat(); + $max = $this->getLFloat(); + $attr = Attribute::getAttribute($id); + + if($attr !== null){ + try{ + $attr->setMinValue($min); + $attr->setMaxValue($max); + $attr->setValue($current); + }catch(\InvalidArgumentException $e){ + throw new BadPacketException($e->getMessage(), 0, $e); //TODO: address this properly + } + $this->attributes[] = $attr; + }else{ + throw new BadPacketException("Unknown attribute type \"$id\""); + } + } + + $this->metadata = $this->getEntityMetadata(); + $linkCount = $this->getUnsignedVarInt(); + for($i = 0; $i < $linkCount; ++$i){ + $this->links[] = $this->getEntityLink(); + } + } + + protected function encodePayload() : void{ + $this->putEntityUniqueId($this->entityUniqueId ?? $this->entityRuntimeId); + $this->putEntityRuntimeId($this->entityRuntimeId); + if(!isset(self::LEGACY_ID_MAP_BC[$this->type])){ + throw new \InvalidArgumentException("Unknown entity numeric ID $this->type"); + } + $this->putString(self::LEGACY_ID_MAP_BC[$this->type]); + $this->putVector3($this->position); + $this->putVector3Nullable($this->motion); + $this->putLFloat($this->pitch); + $this->putLFloat($this->yaw); + $this->putLFloat($this->headYaw); + + $this->putUnsignedVarInt(count($this->attributes)); + foreach($this->attributes as $attribute){ + $this->putString($attribute->getId()); + $this->putLFloat($attribute->getMinValue()); + $this->putLFloat($attribute->getValue()); + $this->putLFloat($attribute->getMaxValue()); + } + + $this->putEntityMetadata($this->metadata); + $this->putUnsignedVarInt(count($this->links)); + foreach($this->links as $link){ + $this->putEntityLink($link); + } + } + + public function handle(PacketHandler $handler) : bool{ + return $handler->handleAddActor($this); + } +} diff --git a/src/pocketmine/network/mcpe/protocol/AddEntityPacket.php b/src/pocketmine/network/mcpe/protocol/AddEntityPacket.php index 3d2a17089..e8a42ec73 100644 --- a/src/pocketmine/network/mcpe/protocol/AddEntityPacket.php +++ b/src/pocketmine/network/mcpe/protocol/AddEntityPacket.php @@ -25,218 +25,33 @@ namespace pocketmine\network\mcpe\protocol; #include -use pocketmine\entity\Attribute; -use pocketmine\entity\EntityIds; -use pocketmine\math\Vector3; -use pocketmine\network\BadPacketException; use pocketmine\network\mcpe\handler\PacketHandler; -use pocketmine\network\mcpe\protocol\types\EntityLink; -use function array_search; -use function count; class AddEntityPacket extends DataPacket implements ClientboundPacket{ public const NETWORK_ID = ProtocolInfo::ADD_ENTITY_PACKET; - /* - * Really really really really really nasty hack, to preserve backwards compatibility. - * We can't transition to string IDs within 3.x because the network IDs (the integer ones) are exposed - * to the API in some places (for god's sake shoghi). - * - * TODO: remove this on 4.0 + /** @var int */ + private $uvarint1; + + public static function create(int $uvarint1) : self{ + $result = new self; + $result->uvarint1 = $uvarint1; + return $result; + } + + /** + * @return int */ - public const LEGACY_ID_MAP_BC = [ - EntityIds::NPC => "minecraft:npc", - EntityIds::PLAYER => "minecraft:player", - EntityIds::WITHER_SKELETON => "minecraft:wither_skeleton", - EntityIds::HUSK => "minecraft:husk", - EntityIds::STRAY => "minecraft:stray", - EntityIds::WITCH => "minecraft:witch", - EntityIds::ZOMBIE_VILLAGER => "minecraft:zombie_villager", - EntityIds::BLAZE => "minecraft:blaze", - EntityIds::MAGMA_CUBE => "minecraft:magma_cube", - EntityIds::GHAST => "minecraft:ghast", - EntityIds::CAVE_SPIDER => "minecraft:cave_spider", - EntityIds::SILVERFISH => "minecraft:silverfish", - EntityIds::ENDERMAN => "minecraft:enderman", - EntityIds::SLIME => "minecraft:slime", - EntityIds::ZOMBIE_PIGMAN => "minecraft:zombie_pigman", - EntityIds::SPIDER => "minecraft:spider", - EntityIds::SKELETON => "minecraft:skeleton", - EntityIds::CREEPER => "minecraft:creeper", - EntityIds::ZOMBIE => "minecraft:zombie", - EntityIds::SKELETON_HORSE => "minecraft:skeleton_horse", - EntityIds::MULE => "minecraft:mule", - EntityIds::DONKEY => "minecraft:donkey", - EntityIds::DOLPHIN => "minecraft:dolphin", - EntityIds::TROPICALFISH => "minecraft:tropicalfish", - EntityIds::WOLF => "minecraft:wolf", - EntityIds::SQUID => "minecraft:squid", - EntityIds::DROWNED => "minecraft:drowned", - EntityIds::SHEEP => "minecraft:sheep", - EntityIds::MOOSHROOM => "minecraft:mooshroom", - EntityIds::PANDA => "minecraft:panda", - EntityIds::SALMON => "minecraft:salmon", - EntityIds::PIG => "minecraft:pig", - EntityIds::VILLAGER => "minecraft:villager", - EntityIds::COD => "minecraft:cod", - EntityIds::PUFFERFISH => "minecraft:pufferfish", - EntityIds::COW => "minecraft:cow", - EntityIds::CHICKEN => "minecraft:chicken", - EntityIds::BALLOON => "minecraft:balloon", - EntityIds::LLAMA => "minecraft:llama", - EntityIds::IRON_GOLEM => "minecraft:iron_golem", - EntityIds::RABBIT => "minecraft:rabbit", - EntityIds::SNOW_GOLEM => "minecraft:snow_golem", - EntityIds::BAT => "minecraft:bat", - EntityIds::OCELOT => "minecraft:ocelot", - EntityIds::HORSE => "minecraft:horse", - EntityIds::CAT => "minecraft:cat", - EntityIds::POLAR_BEAR => "minecraft:polar_bear", - EntityIds::ZOMBIE_HORSE => "minecraft:zombie_horse", - EntityIds::TURTLE => "minecraft:turtle", - EntityIds::PARROT => "minecraft:parrot", - EntityIds::GUARDIAN => "minecraft:guardian", - EntityIds::ELDER_GUARDIAN => "minecraft:elder_guardian", - EntityIds::VINDICATOR => "minecraft:vindicator", - EntityIds::WITHER => "minecraft:wither", - EntityIds::ENDER_DRAGON => "minecraft:ender_dragon", - EntityIds::SHULKER => "minecraft:shulker", - EntityIds::ENDERMITE => "minecraft:endermite", - EntityIds::MINECART => "minecraft:minecart", - EntityIds::HOPPER_MINECART => "minecraft:hopper_minecart", - EntityIds::TNT_MINECART => "minecraft:tnt_minecart", - EntityIds::CHEST_MINECART => "minecraft:chest_minecart", - EntityIds::COMMAND_BLOCK_MINECART => "minecraft:command_block_minecart", - EntityIds::ARMOR_STAND => "minecraft:armor_stand", - EntityIds::ITEM => "minecraft:item", - EntityIds::TNT => "minecraft:tnt", - EntityIds::FALLING_BLOCK => "minecraft:falling_block", - EntityIds::XP_BOTTLE => "minecraft:xp_bottle", - EntityIds::XP_ORB => "minecraft:xp_orb", - EntityIds::EYE_OF_ENDER_SIGNAL => "minecraft:eye_of_ender_signal", - EntityIds::ENDER_CRYSTAL => "minecraft:ender_crystal", - EntityIds::SHULKER_BULLET => "minecraft:shulker_bullet", - EntityIds::FISHING_HOOK => "minecraft:fishing_hook", - EntityIds::DRAGON_FIREBALL => "minecraft:dragon_fireball", - EntityIds::ARROW => "minecraft:arrow", - EntityIds::SNOWBALL => "minecraft:snowball", - EntityIds::EGG => "minecraft:egg", - EntityIds::PAINTING => "minecraft:painting", - EntityIds::THROWN_TRIDENT => "minecraft:thrown_trident", - EntityIds::FIREBALL => "minecraft:fireball", - EntityIds::SPLASH_POTION => "minecraft:splash_potion", - EntityIds::ENDER_PEARL => "minecraft:ender_pearl", - EntityIds::LEASH_KNOT => "minecraft:leash_knot", - EntityIds::WITHER_SKULL => "minecraft:wither_skull", - EntityIds::WITHER_SKULL_DANGEROUS => "minecraft:wither_skull_dangerous", - EntityIds::BOAT => "minecraft:boat", - EntityIds::LIGHTNING_BOLT => "minecraft:lightning_bolt", - EntityIds::SMALL_FIREBALL => "minecraft:small_fireball", - EntityIds::LLAMA_SPIT => "minecraft:llama_spit", - EntityIds::AREA_EFFECT_CLOUD => "minecraft:area_effect_cloud", - EntityIds::LINGERING_POTION => "minecraft:lingering_potion", - EntityIds::FIREWORKS_ROCKET => "minecraft:fireworks_rocket", - EntityIds::EVOCATION_FANG => "minecraft:evocation_fang", - EntityIds::EVOCATION_ILLAGER => "minecraft:evocation_illager", - EntityIds::VEX => "minecraft:vex", - EntityIds::AGENT => "minecraft:agent", - EntityIds::ICE_BOMB => "minecraft:ice_bomb", - EntityIds::PHANTOM => "minecraft:phantom", - EntityIds::TRIPOD_CAMERA => "minecraft:tripod_camera" - ]; - - /** @var int|null */ - public $entityUniqueId = null; //TODO - /** @var int */ - public $entityRuntimeId; - /** @var int */ - public $type; - /** @var Vector3 */ - public $position; - /** @var Vector3|null */ - public $motion; - /** @var float */ - public $pitch = 0.0; - /** @var float */ - public $yaw = 0.0; - /** @var float */ - public $headYaw = 0.0; - - /** @var Attribute[] */ - public $attributes = []; - /** @var array */ - public $metadata = []; - /** @var EntityLink[] */ - public $links = []; + public function getUvarint1() : int{ + return $this->uvarint1; + } protected function decodePayload() : void{ - $this->entityUniqueId = $this->getEntityUniqueId(); - $this->entityRuntimeId = $this->getEntityRuntimeId(); - $this->type = array_search($t = $this->getString(), self::LEGACY_ID_MAP_BC, true); - if($this->type === false){ - throw new BadPacketException("Can't map ID $t to legacy ID"); - } - $this->position = $this->getVector3(); - $this->motion = $this->getVector3(); - $this->pitch = $this->getLFloat(); - $this->yaw = $this->getLFloat(); - $this->headYaw = $this->getLFloat(); - - $attrCount = $this->getUnsignedVarInt(); - for($i = 0; $i < $attrCount; ++$i){ - $id = $this->getString(); - $min = $this->getLFloat(); - $current = $this->getLFloat(); - $max = $this->getLFloat(); - $attr = Attribute::getAttribute($id); - - if($attr !== null){ - try{ - $attr->setMinValue($min); - $attr->setMaxValue($max); - $attr->setValue($current); - }catch(\InvalidArgumentException $e){ - throw new BadPacketException($e->getMessage(), 0, $e); //TODO: address this properly - } - $this->attributes[] = $attr; - }else{ - throw new BadPacketException("Unknown attribute type \"$id\""); - } - } - - $this->metadata = $this->getEntityMetadata(); - $linkCount = $this->getUnsignedVarInt(); - for($i = 0; $i < $linkCount; ++$i){ - $this->links[] = $this->getEntityLink(); - } + $this->uvarint1 = $this->getUnsignedVarInt(); } protected function encodePayload() : void{ - $this->putEntityUniqueId($this->entityUniqueId ?? $this->entityRuntimeId); - $this->putEntityRuntimeId($this->entityRuntimeId); - if(!isset(self::LEGACY_ID_MAP_BC[$this->type])){ - throw new \InvalidArgumentException("Unknown entity numeric ID $this->type"); - } - $this->putString(self::LEGACY_ID_MAP_BC[$this->type]); - $this->putVector3($this->position); - $this->putVector3Nullable($this->motion); - $this->putLFloat($this->pitch); - $this->putLFloat($this->yaw); - $this->putLFloat($this->headYaw); - - $this->putUnsignedVarInt(count($this->attributes)); - foreach($this->attributes as $attribute){ - $this->putString($attribute->getId()); - $this->putLFloat($attribute->getMinValue()); - $this->putLFloat($attribute->getValue()); - $this->putLFloat($attribute->getMaxValue()); - } - - $this->putEntityMetadata($this->metadata); - $this->putUnsignedVarInt(count($this->links)); - foreach($this->links as $link){ - $this->putEntityLink($link); - } + $this->putUnsignedVarInt($this->uvarint1); } public function handle(PacketHandler $handler) : bool{ diff --git a/src/pocketmine/network/mcpe/protocol/AddItemEntityPacket.php b/src/pocketmine/network/mcpe/protocol/AddItemActorPacket.php similarity index 91% rename from src/pocketmine/network/mcpe/protocol/AddItemEntityPacket.php rename to src/pocketmine/network/mcpe/protocol/AddItemActorPacket.php index a42afad5b..5fb28f0f4 100644 --- a/src/pocketmine/network/mcpe/protocol/AddItemEntityPacket.php +++ b/src/pocketmine/network/mcpe/protocol/AddItemActorPacket.php @@ -29,8 +29,8 @@ use pocketmine\item\Item; use pocketmine\math\Vector3; use pocketmine\network\mcpe\handler\PacketHandler; -class AddItemEntityPacket extends DataPacket implements ClientboundPacket{ - public const NETWORK_ID = ProtocolInfo::ADD_ITEM_ENTITY_PACKET; +class AddItemActorPacket extends DataPacket implements ClientboundPacket{ + public const NETWORK_ID = ProtocolInfo::ADD_ITEM_ACTOR_PACKET; /** @var int|null */ public $entityUniqueId = null; //TODO @@ -68,6 +68,6 @@ class AddItemEntityPacket extends DataPacket implements ClientboundPacket{ } public function handle(PacketHandler $handler) : bool{ - return $handler->handleAddItemEntity($this); + return $handler->handleAddItemActor($this); } } diff --git a/src/pocketmine/network/mcpe/protocol/AddPaintingPacket.php b/src/pocketmine/network/mcpe/protocol/AddPaintingPacket.php index 4e2851474..805e1eeab 100644 --- a/src/pocketmine/network/mcpe/protocol/AddPaintingPacket.php +++ b/src/pocketmine/network/mcpe/protocol/AddPaintingPacket.php @@ -25,31 +25,27 @@ namespace pocketmine\network\mcpe\protocol; #include - +use pocketmine\math\Vector3; use pocketmine\network\mcpe\handler\PacketHandler; class AddPaintingPacket extends DataPacket implements ClientboundPacket{ public const NETWORK_ID = ProtocolInfo::ADD_PAINTING_PACKET; - /** @var string */ - public $title; /** @var int|null */ public $entityUniqueId = null; /** @var int */ public $entityRuntimeId; - /** @var int */ - public $x; - /** @var int */ - public $y; - /** @var int */ - public $z; + /** @var Vector3 */ + public $position; /** @var int */ public $direction; + /** @var string */ + public $title; protected function decodePayload() : void{ $this->entityUniqueId = $this->getEntityUniqueId(); $this->entityRuntimeId = $this->getEntityRuntimeId(); - $this->getBlockPosition($this->x, $this->y, $this->z); + $this->position = $this->getVector3(); $this->direction = $this->getVarInt(); $this->title = $this->getString(); } @@ -57,7 +53,7 @@ class AddPaintingPacket extends DataPacket implements ClientboundPacket{ protected function encodePayload() : void{ $this->putEntityUniqueId($this->entityUniqueId ?? $this->entityRuntimeId); $this->putEntityRuntimeId($this->entityRuntimeId); - $this->putBlockPosition($this->x, $this->y, $this->z); + $this->putVector3($this->position); $this->putVarInt($this->direction); $this->putString($this->title); } diff --git a/src/pocketmine/network/mcpe/protocol/AvailableActorIdentifiersPacket.php b/src/pocketmine/network/mcpe/protocol/AvailableActorIdentifiersPacket.php new file mode 100644 index 000000000..ea9c878c5 --- /dev/null +++ b/src/pocketmine/network/mcpe/protocol/AvailableActorIdentifiersPacket.php @@ -0,0 +1,53 @@ + + +use pocketmine\network\mcpe\handler\PacketHandler; +use function base64_decode; + +class AvailableActorIdentifiersPacket extends DataPacket implements ClientboundPacket{ + public const NETWORK_ID = ProtocolInfo::AVAILABLE_ACTOR_IDENTIFIERS_PACKET; + + /** + * Hardcoded NBT blob extracted from MCPE vanilla server. + * TODO: this needs to be generated dynamically, but this is here for stable backwards compatibility, so we don't care for now. + */ + private const HARDCODED_NBT_BLOB = "CgAJBmlkbGlzdArOAQgDYmlkCm1pbmVjcmFmdDoBDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAAgCaWQNbWluZWNyYWZ0Om5wYwMDcmlkhgQBCnN1bW1vbmFibGUAAAgDYmlkAAEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cBCAJpZA1taW5lY3JhZnQ6Y293AwNyaWQWAQpzdW1tb25hYmxlAQAIA2JpZAABDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAQgCaWQabWluZWNyYWZ0OndhbmRlcmluZ190cmFkZXIDA3JpZOwBAQpzdW1tb25hYmxlAQAIA2JpZAABDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAAgCaWQRbWluZWNyYWZ0OmJhbGxvb24DA3JpZNYBAQpzdW1tb25hYmxlAAAIA2JpZAABDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAAgCaWQSbWluZWNyYWZ0OmljZV9ib21iAwNyaWTUAQEKc3VtbW9uYWJsZQAACANiaWQAAQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwEIAmlkDm1pbmVjcmFmdDpodXNrAwNyaWReAQpzdW1tb25hYmxlAQAIA2JpZAABDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAQgCaWQPbWluZWNyYWZ0OnN0cmF5AwNyaWRcAQpzdW1tb25hYmxlAQAIA2JpZAABDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAQgCaWQPbWluZWNyYWZ0OndpdGNoAwNyaWRaAQpzdW1tb25hYmxlAQAIA2JpZAABDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAAgCaWQZbWluZWNyYWZ0OnpvbWJpZV92aWxsYWdlcgMDcmlkWAEKc3VtbW9uYWJsZQEACANiaWQAAQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwEIAmlkD21pbmVjcmFmdDpibGF6ZQMDcmlkVgEKc3VtbW9uYWJsZQEACANiaWQAAQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwEIAmlkFG1pbmVjcmFmdDptYWdtYV9jdWJlAwNyaWRUAQpzdW1tb25hYmxlAQAIA2JpZAABDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAQgCaWQPbWluZWNyYWZ0OmdoYXN0AwNyaWRSAQpzdW1tb25hYmxlAQAIA2JpZAABDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAQgCaWQVbWluZWNyYWZ0OmNhdmVfc3BpZGVyAwNyaWRQAQpzdW1tb25hYmxlAQAIA2JpZAABDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAQgCaWQUbWluZWNyYWZ0OnNpbHZlcmZpc2gDA3JpZE4BCnN1bW1vbmFibGUBAAgDYmlkAAEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cBCAJpZBJtaW5lY3JhZnQ6ZW5kZXJtYW4DA3JpZEwBCnN1bW1vbmFibGUBAAgDYmlkAAEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cBCAJpZA9taW5lY3JhZnQ6c2xpbWUDA3JpZEoBCnN1bW1vbmFibGUBAAgDYmlkAAEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cBCAJpZBdtaW5lY3JhZnQ6em9tYmllX3BpZ21hbgMDcmlkSAEKc3VtbW9uYWJsZQEACANiaWQAAQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwEIAmlkEG1pbmVjcmFmdDpzcGlkZXIDA3JpZEYBCnN1bW1vbmFibGUBAAgDYmlkAAEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cBCAJpZBJtaW5lY3JhZnQ6c2tlbGV0b24DA3JpZEQBCnN1bW1vbmFibGUBAAgDYmlkAAEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cBCAJpZBFtaW5lY3JhZnQ6Y3JlZXBlcgMDcmlkQgEKc3VtbW9uYWJsZQEACANiaWQAAQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwEIAmlkEG1pbmVjcmFmdDp6b21iaWUDA3JpZEABCnN1bW1vbmFibGUBAAgDYmlkAAEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cBCAJpZBhtaW5lY3JhZnQ6c2tlbGV0b25faG9yc2UDA3JpZDQBCnN1bW1vbmFibGUBAAgDYmlkAAEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cBCAJpZA5taW5lY3JhZnQ6bXVsZQMDcmlkMgEKc3VtbW9uYWJsZQEACANiaWQAAQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwEIAmlkEG1pbmVjcmFmdDpkb25rZXkDA3JpZDABCnN1bW1vbmFibGUBAAgDYmlkAAEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cBCAJpZBFtaW5lY3JhZnQ6ZG9scGhpbgMDcmlkPgEKc3VtbW9uYWJsZQEACANiaWQAAQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwEIAmlkFm1pbmVjcmFmdDp6b21iaWVfaG9yc2UDA3JpZDYBCnN1bW1vbmFibGUBAAgDYmlkAAEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cBCAJpZBBtaW5lY3JhZnQ6dHVydGxlAwNyaWSUAQEKc3VtbW9uYWJsZQEACANiaWQAAQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwEIAmlkE21pbmVjcmFmdDptb29zaHJvb20DA3JpZCABCnN1bW1vbmFibGUBAAgDYmlkAAEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cBCAJpZA9taW5lY3JhZnQ6cGFuZGEDA3JpZOIBAQpzdW1tb25hYmxlAQAIA2JpZAABDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAQgCaWQPbWluZWNyYWZ0OmhvcnNlAwNyaWQuAQpzdW1tb25hYmxlAQAIA2JpZAABDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAQgCaWQQbWluZWNyYWZ0OnNhbG1vbgMDcmlk2gEBCnN1bW1vbmFibGUBAAgDYmlkAAEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cBCAJpZA1taW5lY3JhZnQ6cGlnAwNyaWQYAQpzdW1tb25hYmxlAQAIA2JpZAABDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAAgCaWQSbWluZWNyYWZ0OnZpbGxhZ2VyAwNyaWQeAQpzdW1tb25hYmxlAQAIA2JpZAABDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAQgCaWQNbWluZWNyYWZ0OmNvZAMDcmlk4AEBCnN1bW1vbmFibGUBAAgDYmlkAAEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cBCAJpZBRtaW5lY3JhZnQ6cHVmZmVyZmlzaAMDcmlk2AEBCnN1bW1vbmFibGUBAAgDYmlkAAEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cBCAJpZA5taW5lY3JhZnQ6d29sZgMDcmlkHAEKc3VtbW9uYWJsZQEACANiaWQAAQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwEIAmlkFm1pbmVjcmFmdDp0cm9waWNhbGZpc2gDA3JpZN4BAQpzdW1tb25hYmxlAQAIA2JpZAABDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAQgCaWQPbWluZWNyYWZ0OnNoZWVwAwNyaWQaAQpzdW1tb25hYmxlAQAIA2JpZAABDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAQgCaWQRbWluZWNyYWZ0OmRyb3duZWQDA3JpZNwBAQpzdW1tb25hYmxlAQAIA2JpZAABDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAQgCaWQRbWluZWNyYWZ0OmNoaWNrZW4DA3JpZBQBCnN1bW1vbmFibGUBAAgDYmlkAAEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cBCAJpZA9taW5lY3JhZnQ6bGxhbWEDA3JpZDoBCnN1bW1vbmFibGUBAAgDYmlkAAEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cBCAJpZA9taW5lY3JhZnQ6c3F1aWQDA3JpZCIBCnN1bW1vbmFibGUBAAgDYmlkAAEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cBCAJpZBJtaW5lY3JhZnQ6cGlsbGFnZXIDA3JpZOQBAQpzdW1tb25hYmxlAQAIA2JpZAABDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAAgCaWQUbWluZWNyYWZ0Omlyb25fZ29sZW0DA3JpZCgBCnN1bW1vbmFibGUBAAgDYmlkAAEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cBCAJpZBBtaW5lY3JhZnQ6cmFiYml0AwNyaWQkAQpzdW1tb25hYmxlAQAIA2JpZAABDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAQgCaWQVbWluZWNyYWZ0OnZpbGxhZ2VyX3YyAwNyaWTmAQEKc3VtbW9uYWJsZQAACANiaWQAAQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwAIAmlkFG1pbmVjcmFmdDpzbm93X2dvbGVtAwNyaWQqAQpzdW1tb25hYmxlAQAIA2JpZAABDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAQgCaWQNbWluZWNyYWZ0OmJhdAMDcmlkJgEKc3VtbW9uYWJsZQEACANiaWQAAQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwEIAmlkHG1pbmVjcmFmdDp6b21iaWVfdmlsbGFnZXJfdjIDA3JpZOgBAQpzdW1tb25hYmxlAAAIA2JpZAABDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAQgCaWQQbWluZWNyYWZ0Om9jZWxvdAMDcmlkLAEKc3VtbW9uYWJsZQEACANiaWQAAQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwEIAmlkDW1pbmVjcmFmdDpjYXQDA3JpZJYBAQpzdW1tb25hYmxlAQAIA2JpZAABDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAQgCaWQUbWluZWNyYWZ0OnBvbGFyX2JlYXIDA3JpZDgBCnN1bW1vbmFibGUBAAgDYmlkAAEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cBCAJpZBBtaW5lY3JhZnQ6cGFycm90AwNyaWQ8AQpzdW1tb25hYmxlAQAIA2JpZAABDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAQgCaWQZbWluZWNyYWZ0OndpdGhlcl9za2VsZXRvbgMDcmlkYAEKc3VtbW9uYWJsZQEACANiaWQAAQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwEIAmlkEm1pbmVjcmFmdDpndWFyZGlhbgMDcmlkYgEKc3VtbW9uYWJsZQEACANiaWQAAQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwEIAmlkGG1pbmVjcmFmdDplbGRlcl9ndWFyZGlhbgMDcmlkZAEKc3VtbW9uYWJsZQEACANiaWQAAQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwEIAmlkFG1pbmVjcmFmdDp2aW5kaWNhdG9yAwNyaWRyAQpzdW1tb25hYmxlAQAIA2JpZAptaW5lY3JhZnQ6AQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwAIAmlkEG1pbmVjcmFmdDpwbGF5ZXIDA3JpZIIEAQpzdW1tb25hYmxlAAAIA2JpZAABDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAQgCaWQRbWluZWNyYWZ0OnBoYW50b20DA3JpZHQBCnN1bW1vbmFibGUBAAgDYmlkCm1pbmVjcmFmdDoBDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAAgCaWQXbWluZWNyYWZ0OnRyaXBvZF9jYW1lcmEDA3JpZIQEAQpzdW1tb25hYmxlAAAIA2JpZAABDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAQgCaWQRbWluZWNyYWZ0OnJhdmFnZXIDA3JpZHYBCnN1bW1vbmFibGUBAAgDYmlkAAEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cACAJpZBBtaW5lY3JhZnQ6d2l0aGVyAwNyaWRoAQpzdW1tb25hYmxlAQAIA2JpZAABDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAAgCaWQWbWluZWNyYWZ0OmVuZGVyX2RyYWdvbgMDcmlkagEKc3VtbW9uYWJsZQEACANiaWQAAQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwEIAmlkEW1pbmVjcmFmdDpzaHVsa2VyAwNyaWRsAQpzdW1tb25hYmxlAQAIA2JpZAABDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAQgCaWQTbWluZWNyYWZ0OmVuZGVybWl0ZQMDcmlkbgEKc3VtbW9uYWJsZQEACANiaWQAAQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwAIAmlkEm1pbmVjcmFmdDptaW5lY2FydAMDcmlkqAEBCnN1bW1vbmFibGUBAAgDYmlkAAEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cACAJpZBltaW5lY3JhZnQ6aG9wcGVyX21pbmVjYXJ0AwNyaWTAAQEKc3VtbW9uYWJsZQEACANiaWQAAQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwAIAmlkFm1pbmVjcmFmdDp0bnRfbWluZWNhcnQDA3JpZMIBAQpzdW1tb25hYmxlAQAIA2JpZAABDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAAgCaWQYbWluZWNyYWZ0OmNoZXN0X21pbmVjYXJ0AwNyaWTEAQEKc3VtbW9uYWJsZQEACANiaWQAAQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwAIAmlkIG1pbmVjcmFmdDpjb21tYW5kX2Jsb2NrX21pbmVjYXJ0AwNyaWTIAQEKc3VtbW9uYWJsZQEACANiaWQAAQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwAIAmlkFW1pbmVjcmFmdDphcm1vcl9zdGFuZAMDcmlkegEKc3VtbW9uYWJsZQEACANiaWQAAQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwAIAmlkDm1pbmVjcmFmdDppdGVtAwNyaWSAAQEKc3VtbW9uYWJsZQAACANiaWQAAQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwAIAmlkDW1pbmVjcmFmdDp0bnQDA3JpZIIBAQpzdW1tb25hYmxlAQAIA2JpZAABDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAAgCaWQXbWluZWNyYWZ0OmZhbGxpbmdfYmxvY2sDA3JpZIQBAQpzdW1tb25hYmxlAAAIA2JpZAABDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAAgCaWQTbWluZWNyYWZ0OnhwX2JvdHRsZQMDcmlkiAEBCnN1bW1vbmFibGUBAAgDYmlkAAEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cACAJpZBBtaW5lY3JhZnQ6eHBfb3JiAwNyaWSKAQEKc3VtbW9uYWJsZQEACANiaWQAAQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwAIAmlkHW1pbmVjcmFmdDpleWVfb2ZfZW5kZXJfc2lnbmFsAwNyaWSMAQEKc3VtbW9uYWJsZQAACANiaWQAAQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwAIAmlkF21pbmVjcmFmdDplbmRlcl9jcnlzdGFsAwNyaWSOAQEKc3VtbW9uYWJsZQEACANiaWQAAQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwAIAmlkGG1pbmVjcmFmdDpzaHVsa2VyX2J1bGxldAMDcmlkmAEBCnN1bW1vbmFibGUAAAgDYmlkAAEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cACAJpZBZtaW5lY3JhZnQ6ZmlzaGluZ19ob29rAwNyaWSaAQEKc3VtbW9uYWJsZQAACANiaWQAAQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwAIAmlkGW1pbmVjcmFmdDpkcmFnb25fZmlyZWJhbGwDA3JpZJ4BAQpzdW1tb25hYmxlAAAIA2JpZAABDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAAgCaWQPbWluZWNyYWZ0OmFycm93AwNyaWSgAQEKc3VtbW9uYWJsZQEACANiaWQAAQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwAIAmlkEm1pbmVjcmFmdDpzbm93YmFsbAMDcmlkogEBCnN1bW1vbmFibGUBAAgDYmlkAAEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cACAJpZA1taW5lY3JhZnQ6ZWdnAwNyaWSkAQEKc3VtbW9uYWJsZQEACANiaWQAAQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwAIAmlkEm1pbmVjcmFmdDpwYWludGluZwMDcmlkpgEBCnN1bW1vbmFibGUAAAgDYmlkAAEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cACAJpZBhtaW5lY3JhZnQ6dGhyb3duX3RyaWRlbnQDA3JpZJIBAQpzdW1tb25hYmxlAAAIA2JpZAABDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAAgCaWQSbWluZWNyYWZ0OmZpcmViYWxsAwNyaWSqAQEKc3VtbW9uYWJsZQAACANiaWQAAQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwAIAmlkF21pbmVjcmFmdDpzcGxhc2hfcG90aW9uAwNyaWSsAQEKc3VtbW9uYWJsZQEACANiaWQAAQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwAIAmlkFW1pbmVjcmFmdDplbmRlcl9wZWFybAMDcmlkrgEBCnN1bW1vbmFibGUAAAgDYmlkAAEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cACAJpZBRtaW5lY3JhZnQ6bGVhc2hfa25vdAMDcmlksAEBCnN1bW1vbmFibGUBAAgDYmlkAAEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cACAJpZBZtaW5lY3JhZnQ6d2l0aGVyX3NrdWxsAwNyaWSyAQEKc3VtbW9uYWJsZQAACANiaWQAAQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwAIAmlkIG1pbmVjcmFmdDp3aXRoZXJfc2t1bGxfZGFuZ2Vyb3VzAwNyaWS2AQEKc3VtbW9uYWJsZQAACANiaWQAAQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwAIAmlkDm1pbmVjcmFmdDpib2F0AwNyaWS0AQEKc3VtbW9uYWJsZQEACANiaWQAAQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwAIAmlkGG1pbmVjcmFmdDpsaWdodG5pbmdfYm9sdAMDcmlkugEBCnN1bW1vbmFibGUBAAgDYmlkAAEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cACAJpZBhtaW5lY3JhZnQ6c21hbGxfZmlyZWJhbGwDA3JpZLwBAQpzdW1tb25hYmxlAAAIA2JpZAABDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAAgCaWQUbWluZWNyYWZ0OmxsYW1hX3NwaXQDA3JpZMwBAQpzdW1tb25hYmxlAAAIA2JpZAABDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAAgCaWQbbWluZWNyYWZ0OmFyZWFfZWZmZWN0X2Nsb3VkAwNyaWS+AQEKc3VtbW9uYWJsZQAACANiaWQAAQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwAIAmlkGm1pbmVjcmFmdDpsaW5nZXJpbmdfcG90aW9uAwNyaWTKAQEKc3VtbW9uYWJsZQAACANiaWQAAQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwAIAmlkGm1pbmVjcmFmdDpmaXJld29ya3Nfcm9ja2V0AwNyaWSQAQEKc3VtbW9uYWJsZQEACANiaWQAAQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwAIAmlkGG1pbmVjcmFmdDpldm9jYXRpb25fZmFuZwMDcmlkzgEBCnN1bW1vbmFibGUBAAgDYmlkAAEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cBCAJpZBttaW5lY3JhZnQ6ZXZvY2F0aW9uX2lsbGFnZXIDA3JpZNABAQpzdW1tb25hYmxlAQAIA2JpZAABDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAQgCaWQNbWluZWNyYWZ0OnZleAMDcmlk0gEBCnN1bW1vbmFibGUBAAgDYmlkAAEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cACAJpZA9taW5lY3JhZnQ6YWdlbnQDA3JpZHABCnN1bW1vbmFibGUAAAA="; + /** @var string */ + public $namedtag; + + protected function decodePayload() : void{ + $this->namedtag = $this->getRemaining(); + } + + protected function encodePayload() : void{ + $this->put($this->namedtag ?? base64_decode(self::HARDCODED_NBT_BLOB)); + } + + public function handle(PacketHandler $handler) : bool{ + return $handler->handleAvailableActorIdentifiers($this); + } +} diff --git a/src/pocketmine/network/mcpe/protocol/AvailableEntityIdentifiersPacket.php b/src/pocketmine/network/mcpe/protocol/AvailableEntityIdentifiersPacket.php deleted file mode 100644 index a95215d77..000000000 --- a/src/pocketmine/network/mcpe/protocol/AvailableEntityIdentifiersPacket.php +++ /dev/null @@ -1,53 +0,0 @@ - - -use pocketmine\network\mcpe\handler\PacketHandler; -use function base64_decode; - -class AvailableEntityIdentifiersPacket extends DataPacket implements ClientboundPacket{ - public const NETWORK_ID = ProtocolInfo::AVAILABLE_ENTITY_IDENTIFIERS_PACKET; - - /** - * Hardcoded NBT blob extracted from MCPE vanilla server. - * TODO: this needs to be generated dynamically, but this is here for stable backwards compatibility, so we don't care for now. - */ - private const HARDCODED_NBT_BLOB = "CgAJBmlkbGlzdArOAQgDYmlkCm1pbmVjcmFmdDoBDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAAgCaWQNbWluZWNyYWZ0Om5wYwMDcmlkhgQBCnN1bW1vbmFibGUAAAgDYmlkAToBDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAQgCaWQNbWluZWNyYWZ0OmNvdwMDcmlkFgEKc3VtbW9uYWJsZQEACANiaWQBOgEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cBCAJpZBptaW5lY3JhZnQ6d2FuZGVyaW5nX3RyYWRlcgMDcmlk7AEBCnN1bW1vbmFibGUBAAgDYmlkAToBDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAAgCaWQRbWluZWNyYWZ0OmJhbGxvb24DA3JpZNYBAQpzdW1tb25hYmxlAAAIA2JpZAE6AQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwAIAmlkEm1pbmVjcmFmdDppY2VfYm9tYgMDcmlk1AEBCnN1bW1vbmFibGUAAAgDYmlkAToBDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAQgCaWQObWluZWNyYWZ0Omh1c2sDA3JpZF4BCnN1bW1vbmFibGUBAAgDYmlkAToBDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAQgCaWQPbWluZWNyYWZ0OnN0cmF5AwNyaWRcAQpzdW1tb25hYmxlAQAIA2JpZAE6AQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwEIAmlkD21pbmVjcmFmdDp3aXRjaAMDcmlkWgEKc3VtbW9uYWJsZQEACANiaWQBOgEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cACAJpZBltaW5lY3JhZnQ6em9tYmllX3ZpbGxhZ2VyAwNyaWRYAQpzdW1tb25hYmxlAQAIA2JpZAE6AQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwEIAmlkD21pbmVjcmFmdDpibGF6ZQMDcmlkVgEKc3VtbW9uYWJsZQEACANiaWQBOgEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cBCAJpZBRtaW5lY3JhZnQ6bWFnbWFfY3ViZQMDcmlkVAEKc3VtbW9uYWJsZQEACANiaWQBOgEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cBCAJpZA9taW5lY3JhZnQ6Z2hhc3QDA3JpZFIBCnN1bW1vbmFibGUBAAgDYmlkAToBDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAQgCaWQVbWluZWNyYWZ0OmNhdmVfc3BpZGVyAwNyaWRQAQpzdW1tb25hYmxlAQAIA2JpZAE6AQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwEIAmlkFG1pbmVjcmFmdDpzaWx2ZXJmaXNoAwNyaWROAQpzdW1tb25hYmxlAQAIA2JpZAE6AQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwEIAmlkEm1pbmVjcmFmdDplbmRlcm1hbgMDcmlkTAEKc3VtbW9uYWJsZQEACANiaWQBOgEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cBCAJpZA9taW5lY3JhZnQ6c2xpbWUDA3JpZEoBCnN1bW1vbmFibGUBAAgDYmlkAToBDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAQgCaWQXbWluZWNyYWZ0OnpvbWJpZV9waWdtYW4DA3JpZEgBCnN1bW1vbmFibGUBAAgDYmlkAToBDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAQgCaWQQbWluZWNyYWZ0OnNwaWRlcgMDcmlkRgEKc3VtbW9uYWJsZQEACANiaWQBOgEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cBCAJpZBJtaW5lY3JhZnQ6c2tlbGV0b24DA3JpZEQBCnN1bW1vbmFibGUBAAgDYmlkAToBDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAQgCaWQRbWluZWNyYWZ0OmNyZWVwZXIDA3JpZEIBCnN1bW1vbmFibGUBAAgDYmlkAToBDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAQgCaWQQbWluZWNyYWZ0OnpvbWJpZQMDcmlkQAEKc3VtbW9uYWJsZQEACANiaWQBOgEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cBCAJpZBhtaW5lY3JhZnQ6c2tlbGV0b25faG9yc2UDA3JpZDQBCnN1bW1vbmFibGUBAAgDYmlkAToBDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAQgCaWQObWluZWNyYWZ0Om11bGUDA3JpZDIBCnN1bW1vbmFibGUBAAgDYmlkAToBDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAQgCaWQQbWluZWNyYWZ0OmRvbmtleQMDcmlkMAEKc3VtbW9uYWJsZQEACANiaWQBOgEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cBCAJpZBFtaW5lY3JhZnQ6ZG9scGhpbgMDcmlkPgEKc3VtbW9uYWJsZQEACANiaWQBOgEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cBCAJpZBZtaW5lY3JhZnQ6em9tYmllX2hvcnNlAwNyaWQ2AQpzdW1tb25hYmxlAQAIA2JpZAE6AQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwEIAmlkEG1pbmVjcmFmdDp0dXJ0bGUDA3JpZJQBAQpzdW1tb25hYmxlAQAIA2JpZAE6AQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwEIAmlkE21pbmVjcmFmdDptb29zaHJvb20DA3JpZCABCnN1bW1vbmFibGUBAAgDYmlkAToBDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAQgCaWQPbWluZWNyYWZ0OnBhbmRhAwNyaWTiAQEKc3VtbW9uYWJsZQEACANiaWQBOgEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cBCAJpZA9taW5lY3JhZnQ6aG9yc2UDA3JpZC4BCnN1bW1vbmFibGUBAAgDYmlkAToBDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAQgCaWQQbWluZWNyYWZ0OnNhbG1vbgMDcmlk2gEBCnN1bW1vbmFibGUBAAgDYmlkAToBDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAQgCaWQNbWluZWNyYWZ0OnBpZwMDcmlkGAEKc3VtbW9uYWJsZQEACANiaWQBOgEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cACAJpZBJtaW5lY3JhZnQ6dmlsbGFnZXIDA3JpZB4BCnN1bW1vbmFibGUBAAgDYmlkAToBDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAQgCaWQNbWluZWNyYWZ0OmNvZAMDcmlk4AEBCnN1bW1vbmFibGUBAAgDYmlkAToBDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAQgCaWQUbWluZWNyYWZ0OnB1ZmZlcmZpc2gDA3JpZNgBAQpzdW1tb25hYmxlAQAIA2JpZAE6AQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwEIAmlkDm1pbmVjcmFmdDp3b2xmAwNyaWQcAQpzdW1tb25hYmxlAQAIA2JpZAE6AQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwEIAmlkFm1pbmVjcmFmdDp0cm9waWNhbGZpc2gDA3JpZN4BAQpzdW1tb25hYmxlAQAIA2JpZAE6AQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwEIAmlkD21pbmVjcmFmdDpzaGVlcAMDcmlkGgEKc3VtbW9uYWJsZQEACANiaWQBOgEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cBCAJpZBFtaW5lY3JhZnQ6ZHJvd25lZAMDcmlk3AEBCnN1bW1vbmFibGUBAAgDYmlkAToBDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAQgCaWQRbWluZWNyYWZ0OmNoaWNrZW4DA3JpZBQBCnN1bW1vbmFibGUBAAgDYmlkAToBDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAQgCaWQPbWluZWNyYWZ0OmxsYW1hAwNyaWQ6AQpzdW1tb25hYmxlAQAIA2JpZAE6AQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwEIAmlkD21pbmVjcmFmdDpzcXVpZAMDcmlkIgEKc3VtbW9uYWJsZQEACANiaWQBOgEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cBCAJpZBJtaW5lY3JhZnQ6cGlsbGFnZXIDA3JpZOQBAQpzdW1tb25hYmxlAQAIA2JpZAE6AQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwAIAmlkFG1pbmVjcmFmdDppcm9uX2dvbGVtAwNyaWQoAQpzdW1tb25hYmxlAQAIA2JpZAE6AQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwEIAmlkEG1pbmVjcmFmdDpyYWJiaXQDA3JpZCQBCnN1bW1vbmFibGUBAAgDYmlkAToBDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAQgCaWQVbWluZWNyYWZ0OnZpbGxhZ2VyX3YyAwNyaWTmAQEKc3VtbW9uYWJsZQAACANiaWQBOgEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cACAJpZBRtaW5lY3JhZnQ6c25vd19nb2xlbQMDcmlkKgEKc3VtbW9uYWJsZQEACANiaWQBOgEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cBCAJpZA1taW5lY3JhZnQ6YmF0AwNyaWQmAQpzdW1tb25hYmxlAQAIA2JpZAE6AQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwEIAmlkHG1pbmVjcmFmdDp6b21iaWVfdmlsbGFnZXJfdjIDA3JpZOgBAQpzdW1tb25hYmxlAAAIA2JpZAE6AQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwEIAmlkEG1pbmVjcmFmdDpvY2Vsb3QDA3JpZCwBCnN1bW1vbmFibGUBAAgDYmlkAToBDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAQgCaWQNbWluZWNyYWZ0OmNhdAMDcmlklgEBCnN1bW1vbmFibGUBAAgDYmlkAToBDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAQgCaWQUbWluZWNyYWZ0OnBvbGFyX2JlYXIDA3JpZDgBCnN1bW1vbmFibGUBAAgDYmlkAToBDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAQgCaWQQbWluZWNyYWZ0OnBhcnJvdAMDcmlkPAEKc3VtbW9uYWJsZQEACANiaWQBOgEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cBCAJpZBltaW5lY3JhZnQ6d2l0aGVyX3NrZWxldG9uAwNyaWRgAQpzdW1tb25hYmxlAQAIA2JpZAE6AQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwEIAmlkEm1pbmVjcmFmdDpndWFyZGlhbgMDcmlkYgEKc3VtbW9uYWJsZQEACANiaWQBOgEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cBCAJpZBhtaW5lY3JhZnQ6ZWxkZXJfZ3VhcmRpYW4DA3JpZGQBCnN1bW1vbmFibGUBAAgDYmlkAToBDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAQgCaWQUbWluZWNyYWZ0OnZpbmRpY2F0b3IDA3JpZHIBCnN1bW1vbmFibGUBAAgDYmlkCm1pbmVjcmFmdDoBDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAAgCaWQQbWluZWNyYWZ0OnBsYXllcgMDcmlkggQBCnN1bW1vbmFibGUAAAgDYmlkAToBDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAQgCaWQRbWluZWNyYWZ0OnBoYW50b20DA3JpZHQBCnN1bW1vbmFibGUBAAgDYmlkCm1pbmVjcmFmdDoBDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAAgCaWQXbWluZWNyYWZ0OnRyaXBvZF9jYW1lcmEDA3JpZIQEAQpzdW1tb25hYmxlAAAIA2JpZAE6AQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwEIAmlkEW1pbmVjcmFmdDpyYXZhZ2VyAwNyaWR2AQpzdW1tb25hYmxlAQAIA2JpZAE6AQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwAIAmlkEG1pbmVjcmFmdDp3aXRoZXIDA3JpZGgBCnN1bW1vbmFibGUBAAgDYmlkAToBDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAAgCaWQWbWluZWNyYWZ0OmVuZGVyX2RyYWdvbgMDcmlkagEKc3VtbW9uYWJsZQEACANiaWQBOgEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cBCAJpZBFtaW5lY3JhZnQ6c2h1bGtlcgMDcmlkbAEKc3VtbW9uYWJsZQEACANiaWQBOgEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cBCAJpZBNtaW5lY3JhZnQ6ZW5kZXJtaXRlAwNyaWRuAQpzdW1tb25hYmxlAQAIA2JpZAE6AQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwAIAmlkEm1pbmVjcmFmdDptaW5lY2FydAMDcmlkqAEBCnN1bW1vbmFibGUBAAgDYmlkAToBDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAAgCaWQZbWluZWNyYWZ0OmhvcHBlcl9taW5lY2FydAMDcmlkwAEBCnN1bW1vbmFibGUBAAgDYmlkAToBDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAAgCaWQWbWluZWNyYWZ0OnRudF9taW5lY2FydAMDcmlkwgEBCnN1bW1vbmFibGUBAAgDYmlkAToBDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAAgCaWQYbWluZWNyYWZ0OmNoZXN0X21pbmVjYXJ0AwNyaWTEAQEKc3VtbW9uYWJsZQEACANiaWQBOgEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cACAJpZCBtaW5lY3JhZnQ6Y29tbWFuZF9ibG9ja19taW5lY2FydAMDcmlkyAEBCnN1bW1vbmFibGUBAAgDYmlkAToBDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAAgCaWQVbWluZWNyYWZ0OmFybW9yX3N0YW5kAwNyaWR6AQpzdW1tb25hYmxlAQAIA2JpZAE6AQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwAIAmlkDm1pbmVjcmFmdDppdGVtAwNyaWSAAQEKc3VtbW9uYWJsZQAACANiaWQBOgEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cACAJpZA1taW5lY3JhZnQ6dG50AwNyaWSCAQEKc3VtbW9uYWJsZQEACANiaWQBOgEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cACAJpZBdtaW5lY3JhZnQ6ZmFsbGluZ19ibG9jawMDcmlkhAEBCnN1bW1vbmFibGUAAAgDYmlkAToBDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAAgCaWQTbWluZWNyYWZ0OnhwX2JvdHRsZQMDcmlkiAEBCnN1bW1vbmFibGUBAAgDYmlkAToBDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAAgCaWQQbWluZWNyYWZ0OnhwX29yYgMDcmlkigEBCnN1bW1vbmFibGUBAAgDYmlkAToBDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAAgCaWQdbWluZWNyYWZ0OmV5ZV9vZl9lbmRlcl9zaWduYWwDA3JpZIwBAQpzdW1tb25hYmxlAAAIA2JpZAE6AQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwAIAmlkF21pbmVjcmFmdDplbmRlcl9jcnlzdGFsAwNyaWSOAQEKc3VtbW9uYWJsZQEACANiaWQBOgEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cACAJpZBhtaW5lY3JhZnQ6c2h1bGtlcl9idWxsZXQDA3JpZJgBAQpzdW1tb25hYmxlAAAIA2JpZAE6AQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwAIAmlkFm1pbmVjcmFmdDpmaXNoaW5nX2hvb2sDA3JpZJoBAQpzdW1tb25hYmxlAAAIA2JpZAE6AQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwAIAmlkGW1pbmVjcmFmdDpkcmFnb25fZmlyZWJhbGwDA3JpZJ4BAQpzdW1tb25hYmxlAAAIA2JpZAE6AQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwAIAmlkD21pbmVjcmFmdDphcnJvdwMDcmlkoAEBCnN1bW1vbmFibGUBAAgDYmlkAToBDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAAgCaWQSbWluZWNyYWZ0OnNub3diYWxsAwNyaWSiAQEKc3VtbW9uYWJsZQEACANiaWQBOgEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cACAJpZA1taW5lY3JhZnQ6ZWdnAwNyaWSkAQEKc3VtbW9uYWJsZQEACANiaWQBOgEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cACAJpZBJtaW5lY3JhZnQ6cGFpbnRpbmcDA3JpZKYBAQpzdW1tb25hYmxlAAAIA2JpZAE6AQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwAIAmlkGG1pbmVjcmFmdDp0aHJvd25fdHJpZGVudAMDcmlkkgEBCnN1bW1vbmFibGUAAAgDYmlkAToBDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAAgCaWQSbWluZWNyYWZ0OmZpcmViYWxsAwNyaWSqAQEKc3VtbW9uYWJsZQAACANiaWQBOgEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cACAJpZBdtaW5lY3JhZnQ6c3BsYXNoX3BvdGlvbgMDcmlkrAEBCnN1bW1vbmFibGUBAAgDYmlkAToBDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAAgCaWQVbWluZWNyYWZ0OmVuZGVyX3BlYXJsAwNyaWSuAQEKc3VtbW9uYWJsZQAACANiaWQBOgEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cACAJpZBRtaW5lY3JhZnQ6bGVhc2hfa25vdAMDcmlksAEBCnN1bW1vbmFibGUBAAgDYmlkAToBDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAAgCaWQWbWluZWNyYWZ0OndpdGhlcl9za3VsbAMDcmlksgEBCnN1bW1vbmFibGUAAAgDYmlkAToBDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAAgCaWQgbWluZWNyYWZ0OndpdGhlcl9za3VsbF9kYW5nZXJvdXMDA3JpZLYBAQpzdW1tb25hYmxlAAAIA2JpZAE6AQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwAIAmlkDm1pbmVjcmFmdDpib2F0AwNyaWS0AQEKc3VtbW9uYWJsZQEACANiaWQBOgEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cACAJpZBhtaW5lY3JhZnQ6bGlnaHRuaW5nX2JvbHQDA3JpZLoBAQpzdW1tb25hYmxlAQAIA2JpZAE6AQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwAIAmlkGG1pbmVjcmFmdDpzbWFsbF9maXJlYmFsbAMDcmlkvAEBCnN1bW1vbmFibGUAAAgDYmlkAToBDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAAgCaWQUbWluZWNyYWZ0OmxsYW1hX3NwaXQDA3JpZMwBAQpzdW1tb25hYmxlAAAIA2JpZAE6AQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwAIAmlkG21pbmVjcmFmdDphcmVhX2VmZmVjdF9jbG91ZAMDcmlkvgEBCnN1bW1vbmFibGUAAAgDYmlkAToBDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAAgCaWQabWluZWNyYWZ0OmxpbmdlcmluZ19wb3Rpb24DA3JpZMoBAQpzdW1tb25hYmxlAAAIA2JpZAE6AQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwAIAmlkGm1pbmVjcmFmdDpmaXJld29ya3Nfcm9ja2V0AwNyaWSQAQEKc3VtbW9uYWJsZQEACANiaWQBOgEMZXhwZXJpbWVudGFsAAELaGFzc3Bhd25lZ2cACAJpZBhtaW5lY3JhZnQ6ZXZvY2F0aW9uX2ZhbmcDA3JpZM4BAQpzdW1tb25hYmxlAQAIA2JpZAE6AQxleHBlcmltZW50YWwAAQtoYXNzcGF3bmVnZwEIAmlkG21pbmVjcmFmdDpldm9jYXRpb25faWxsYWdlcgMDcmlk0AEBCnN1bW1vbmFibGUBAAgDYmlkAToBDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAQgCaWQNbWluZWNyYWZ0OnZleAMDcmlk0gEBCnN1bW1vbmFibGUBAAgDYmlkAToBDGV4cGVyaW1lbnRhbAABC2hhc3NwYXduZWdnAAgCaWQPbWluZWNyYWZ0OmFnZW50AwNyaWRwAQpzdW1tb25hYmxlAAAA"; - /** @var string */ - public $namedtag; - - protected function decodePayload() : void{ - $this->namedtag = $this->getRemaining(); - } - - protected function encodePayload() : void{ - $this->put($this->namedtag ?? base64_decode(self::HARDCODED_NBT_BLOB)); - } - - public function handle(PacketHandler $handler) : bool{ - return $handler->handleAvailableEntityIdentifiers($this); - } -} diff --git a/src/pocketmine/network/mcpe/protocol/BlockEntityDataPacket.php b/src/pocketmine/network/mcpe/protocol/BlockActorDataPacket.php similarity index 87% rename from src/pocketmine/network/mcpe/protocol/BlockEntityDataPacket.php rename to src/pocketmine/network/mcpe/protocol/BlockActorDataPacket.php index 102419323..6e4b428e5 100644 --- a/src/pocketmine/network/mcpe/protocol/BlockEntityDataPacket.php +++ b/src/pocketmine/network/mcpe/protocol/BlockActorDataPacket.php @@ -28,8 +28,8 @@ namespace pocketmine\network\mcpe\protocol; use pocketmine\network\mcpe\handler\PacketHandler; -class BlockEntityDataPacket extends DataPacket implements ClientboundPacket, ServerboundPacket{ - public const NETWORK_ID = ProtocolInfo::BLOCK_ENTITY_DATA_PACKET; +class BlockActorDataPacket extends DataPacket implements ClientboundPacket, ServerboundPacket{ + public const NETWORK_ID = ProtocolInfo::BLOCK_ACTOR_DATA_PACKET; /** @var int */ public $x; @@ -58,6 +58,6 @@ class BlockEntityDataPacket extends DataPacket implements ClientboundPacket, Ser } public function handle(PacketHandler $handler) : bool{ - return $handler->handleBlockEntityData($this); + return $handler->handleBlockActorData($this); } } diff --git a/src/pocketmine/network/mcpe/protocol/ClientCacheBlobStatusPacket.php b/src/pocketmine/network/mcpe/protocol/ClientCacheBlobStatusPacket.php new file mode 100644 index 000000000..35693516c --- /dev/null +++ b/src/pocketmine/network/mcpe/protocol/ClientCacheBlobStatusPacket.php @@ -0,0 +1,95 @@ + + +use pocketmine\network\mcpe\handler\PacketHandler; +use function count; + +class ClientCacheBlobStatusPacket extends DataPacket implements ServerboundPacket{ + public const NETWORK_ID = ProtocolInfo::CLIENT_CACHE_BLOB_STATUS_PACKET; + + /** @var int[] xxHash64 subchunk data hashes */ + private $hitHashes = []; + /** @var int[] xxHash64 subchunk data hashes */ + private $missHashes = []; + + /** + * @param int[] $hitHashes + * @param int[] $missHashes + * + * @return self + */ + public static function create(array $hitHashes, array $missHashes) : self{ + //type checks + (static function(int ...$hashes){})(...$hitHashes); + (static function(int ...$hashes){})(...$missHashes); + + $result = new self; + $result->hitHashes = $hitHashes; + $result->missHashes = $missHashes; + return $result; + } + + /** + * @return int[] + */ + public function getHitHashes() : array{ + return $this->hitHashes; + } + + /** + * @return int[] + */ + public function getMissHashes() : array{ + return $this->missHashes; + } + + protected function decodePayload() : void{ + $hitCount = $this->getUnsignedVarInt(); + $missCount = $this->getUnsignedVarInt(); + for($i = 0; $i < $hitCount; ++$i){ + $this->hitHashes[] = $this->getLLong(); + } + for($i = 0; $i < $missCount; ++$i){ + $this->missHashes[] = $this->getLLong(); + } + } + + protected function encodePayload() : void{ + $this->putUnsignedVarInt(count($this->hitHashes)); + $this->putUnsignedVarInt(count($this->missHashes)); + foreach($this->hitHashes as $hash){ + $this->putLLong($hash); + } + foreach($this->missHashes as $hash){ + $this->putLLong($hash); + } + } + + public function handle(PacketHandler $handler) : bool{ + return $handler->handleClientCacheBlobStatus($this); + } +} diff --git a/src/pocketmine/network/mcpe/protocol/ClientCacheMissResponsePacket.php b/src/pocketmine/network/mcpe/protocol/ClientCacheMissResponsePacket.php new file mode 100644 index 000000000..11defadd6 --- /dev/null +++ b/src/pocketmine/network/mcpe/protocol/ClientCacheMissResponsePacket.php @@ -0,0 +1,78 @@ + + +use pocketmine\network\mcpe\handler\PacketHandler; +use pocketmine\network\mcpe\protocol\types\ChunkCacheBlob; +use function count; + +class ClientCacheMissResponsePacket extends DataPacket implements ClientboundPacket{ + public const NETWORK_ID = ProtocolInfo::CLIENT_CACHE_MISS_RESPONSE_PACKET; + + /** @var ChunkCacheBlob[] */ + private $blobs = []; + + /** + * @param ChunkCacheBlob[] $blobs + * + * @return self + */ + public static function create(array $blobs) : self{ + //type check + (static function(ChunkCacheBlob ...$blobs){})($blobs); + + $result = new self; + $result->blobs = $blobs; + return $result; + } + + /** + * @return ChunkCacheBlob[] + */ + public function getBlobs() : array{ + return $this->blobs; + } + + protected function decodePayload() : void{ + for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){ + $hash = $this->getLLong(); + $payload = $this->getString(); + $this->blobs[] = new ChunkCacheBlob($hash, $payload); + } + } + + protected function encodePayload() : void{ + $this->putUnsignedVarInt(count($this->blobs)); + foreach($this->blobs as $blob){ + $this->putLLong($blob->getHash()); + $this->putString($blob->getPayload()); + } + } + + public function handle(PacketHandler $handler) : bool{ + return $handler->handleClientCacheMissResponse($this); + } +} diff --git a/src/pocketmine/network/mcpe/protocol/ClientCacheStatusPacket.php b/src/pocketmine/network/mcpe/protocol/ClientCacheStatusPacket.php new file mode 100644 index 000000000..cfa97c8e2 --- /dev/null +++ b/src/pocketmine/network/mcpe/protocol/ClientCacheStatusPacket.php @@ -0,0 +1,60 @@ + + +use pocketmine\network\mcpe\handler\PacketHandler; + +class ClientCacheStatusPacket extends DataPacket implements ServerboundPacket{ + public const NETWORK_ID = ProtocolInfo::CLIENT_CACHE_STATUS_PACKET; + + /** @var bool */ + private $enabled; + + public static function create(bool $enabled) : self{ + $result = new self; + $result->enabled = $enabled; + return $result; + } + + /** + * @return bool + */ + public function isEnabled() : bool{ + return $this->enabled; + } + + protected function decodePayload() : void{ + $this->enabled = $this->getBool(); + } + + protected function encodePayload() : void{ + $this->putBool($this->enabled); + } + + public function handle(PacketHandler $handler) : bool{ + return $handler->handleClientCacheStatus($this); + } +} diff --git a/src/pocketmine/network/mcpe/protocol/CommandBlockUpdatePacket.php b/src/pocketmine/network/mcpe/protocol/CommandBlockUpdatePacket.php index 818b312ad..51b610db5 100644 --- a/src/pocketmine/network/mcpe/protocol/CommandBlockUpdatePacket.php +++ b/src/pocketmine/network/mcpe/protocol/CommandBlockUpdatePacket.php @@ -59,6 +59,10 @@ class CommandBlockUpdatePacket extends DataPacket implements ServerboundPacket{ public $name; /** @var bool */ public $shouldTrackOutput; + /** @var int */ + public $tickDelay; + /** @var bool */ + public $executeOnFirstTick; protected function decodePayload() : void{ $this->isBlock = $this->getBool(); @@ -78,6 +82,8 @@ class CommandBlockUpdatePacket extends DataPacket implements ServerboundPacket{ $this->name = $this->getString(); $this->shouldTrackOutput = $this->getBool(); + $this->tickDelay = $this->getLInt(); + $this->executeOnFirstTick = $this->getBool(); } protected function encodePayload() : void{ @@ -97,6 +103,8 @@ class CommandBlockUpdatePacket extends DataPacket implements ServerboundPacket{ $this->putString($this->name); $this->putBool($this->shouldTrackOutput); + $this->putLInt($this->tickDelay); + $this->putBool($this->executeOnFirstTick); } public function handle(PacketHandler $handler) : bool{ diff --git a/src/pocketmine/network/mcpe/protocol/CraftingDataPacket.php b/src/pocketmine/network/mcpe/protocol/CraftingDataPacket.php index eab5be269..d337ca873 100644 --- a/src/pocketmine/network/mcpe/protocol/CraftingDataPacket.php +++ b/src/pocketmine/network/mcpe/protocol/CraftingDataPacket.php @@ -34,6 +34,9 @@ use pocketmine\item\ItemFactory; use pocketmine\network\BadPacketException; use pocketmine\network\mcpe\handler\PacketHandler; use pocketmine\network\mcpe\serializer\NetworkBinaryStream; +#ifndef COMPILE +use pocketmine\utils\Binary; +#endif use function count; use function str_repeat; @@ -67,11 +70,13 @@ class CraftingDataPacket extends DataPacket implements ClientboundPacket{ case self::ENTRY_SHAPELESS: case self::ENTRY_SHULKER_BOX: case self::ENTRY_SHAPELESS_CHEMISTRY: + $entry["recipe_id"] = $this->getString(); $ingredientCount = $this->getUnsignedVarInt(); /** @var Item */ $entry["input"] = []; for($j = 0; $j < $ingredientCount; ++$j){ - $entry["input"][] = $this->getSlot(); + $entry["input"][] = $in = $this->getRecipeIngredient(); + $in->setCount(1); //TODO HACK: they send a useless count field which breaks the PM crafting system because it isn't always 1 } $resultCount = $this->getUnsignedVarInt(); $entry["output"] = []; @@ -80,16 +85,19 @@ class CraftingDataPacket extends DataPacket implements ClientboundPacket{ } $entry["uuid"] = $this->getUUID()->toString(); $entry["block"] = $this->getString(); + $entry["priority"] = $this->getVarInt(); break; case self::ENTRY_SHAPED: case self::ENTRY_SHAPED_CHEMISTRY: + $entry["recipe_id"] = $this->getString(); $entry["width"] = $this->getVarInt(); $entry["height"] = $this->getVarInt(); $count = $entry["width"] * $entry["height"]; $entry["input"] = []; for($j = 0; $j < $count; ++$j){ - $entry["input"][] = $this->getSlot(); + $entry["input"][] = $in = $this->getRecipeIngredient(); + $in->setCount(1); //TODO HACK: they send a useless count field which breaks the PM crafting system } $resultCount = $this->getUnsignedVarInt(); $entry["output"] = []; @@ -98,6 +106,7 @@ class CraftingDataPacket extends DataPacket implements ClientboundPacket{ } $entry["uuid"] = $this->getUUID()->toString(); $entry["block"] = $this->getString(); + $entry["priority"] = $this->getVarInt(); break; case self::ENTRY_FURNACE: @@ -115,7 +124,10 @@ class CraftingDataPacket extends DataPacket implements ClientboundPacket{ }catch(\InvalidArgumentException $e){ throw new BadPacketException($e->getMessage(), 0, $e); } - $entry["output"] = $this->getSlot(); + $entry["output"] = $out = $this->getSlot(); + if($out->getMeta() === 0x7fff){ + $entry["output"] = ItemFactory::get($out->getId(), 0); //TODO HACK: some 1.12 furnace recipe outputs have wildcard damage values + } $entry["block"] = $this->getString(); break; @@ -130,11 +142,11 @@ class CraftingDataPacket extends DataPacket implements ClientboundPacket{ $this->getBool(); //cleanRecipes } - private static function writeEntry($entry, NetworkBinaryStream $stream) : int{ + private static function writeEntry($entry, NetworkBinaryStream $stream, int $pos) : int{ if($entry instanceof ShapelessRecipe){ - return self::writeShapelessRecipe($entry, $stream); + return self::writeShapelessRecipe($entry, $stream, $pos); }elseif($entry instanceof ShapedRecipe){ - return self::writeShapedRecipe($entry, $stream); + return self::writeShapedRecipe($entry, $stream, $pos); }elseif($entry instanceof FurnaceRecipe){ return self::writeFurnaceRecipe($entry, $stream); } @@ -143,10 +155,11 @@ class CraftingDataPacket extends DataPacket implements ClientboundPacket{ return -1; } - private static function writeShapelessRecipe(ShapelessRecipe $recipe, NetworkBinaryStream $stream) : int{ + private static function writeShapelessRecipe(ShapelessRecipe $recipe, NetworkBinaryStream $stream, int $pos) : int{ + $stream->putString(Binary::writeInt($pos)); //some kind of recipe ID, doesn't matter what it is as long as it's unique $stream->putUnsignedVarInt($recipe->getIngredientCount()); foreach($recipe->getIngredientList() as $item){ - $stream->putSlot($item); + $stream->putRecipeIngredient($item); } $results = $recipe->getResults(); @@ -157,17 +170,19 @@ class CraftingDataPacket extends DataPacket implements ClientboundPacket{ $stream->put(str_repeat("\x00", 16)); //Null UUID $stream->putString("crafting_table"); //TODO: blocktype (no prefix) (this might require internal API breaks) + $stream->putVarInt(50); //TODO: priority return CraftingDataPacket::ENTRY_SHAPELESS; } - private static function writeShapedRecipe(ShapedRecipe $recipe, NetworkBinaryStream $stream) : int{ + private static function writeShapedRecipe(ShapedRecipe $recipe, NetworkBinaryStream $stream, int $pos) : int{ + $stream->putString(Binary::writeInt($pos)); //some kind of recipe ID, doesn't matter what it is as long as it's unique $stream->putVarInt($recipe->getWidth()); $stream->putVarInt($recipe->getHeight()); for($z = 0; $z < $recipe->getHeight(); ++$z){ for($x = 0; $x < $recipe->getWidth(); ++$x){ - $stream->putSlot($recipe->getIngredient($x, $z)); + $stream->putRecipeIngredient($recipe->getIngredient($x, $z)); } } @@ -179,6 +194,7 @@ class CraftingDataPacket extends DataPacket implements ClientboundPacket{ $stream->put(str_repeat("\x00", 16)); //Null UUID $stream->putString("crafting_table"); //TODO: blocktype (no prefix) (this might require internal API breaks) + $stream->putVarInt(50); //TODO: priority return CraftingDataPacket::ENTRY_SHAPED; } @@ -211,8 +227,9 @@ class CraftingDataPacket extends DataPacket implements ClientboundPacket{ $this->putUnsignedVarInt(count($this->entries)); $writer = new NetworkBinaryStream(); + $counter = 0; foreach($this->entries as $d){ - $entryType = self::writeEntry($d, $writer); + $entryType = self::writeEntry($d, $writer, $counter++); if($entryType >= 0){ $this->putVarInt($entryType); $this->put($writer->getBuffer()); diff --git a/src/pocketmine/network/mcpe/protocol/LevelChunkPacket.php b/src/pocketmine/network/mcpe/protocol/LevelChunkPacket.php new file mode 100644 index 000000000..fe4818287 --- /dev/null +++ b/src/pocketmine/network/mcpe/protocol/LevelChunkPacket.php @@ -0,0 +1,145 @@ + + +use pocketmine\network\mcpe\handler\PacketHandler; +use function count; + +class LevelChunkPacket extends DataPacket implements ClientboundPacket{ + public const NETWORK_ID = ProtocolInfo::LEVEL_CHUNK_PACKET; + + /** @var int */ + private $chunkX; + /** @var int */ + private $chunkZ; + /** @var int */ + private $subChunkCount; + /** @var bool */ + private $cacheEnabled; + /** @var int[] */ + private $usedBlobHashes = []; + /** @var string */ + private $extraPayload; + + public static function withoutCache(int $chunkX, int $chunkZ, int $subChunkCount, string $payload) : self{ + $result = new self; + $result->chunkX = $chunkX; + $result->chunkZ = $chunkZ; + $result->subChunkCount = $subChunkCount; + $result->extraPayload = $payload; + + $result->cacheEnabled = false; + + return $result; + } + + public static function withCache(int $chunkX, int $chunkZ, int $subChunkCount, array $usedBlobHashes, string $extraPayload) : self{ + (static function(int ...$hashes){})($usedBlobHashes); + $result = new self; + $result->chunkX = $chunkX; + $result->chunkZ = $chunkZ; + $result->subChunkCount = $subChunkCount; + $result->extraPayload = $extraPayload; + + $result->cacheEnabled = true; + $result->usedBlobHashes = $usedBlobHashes; + + return $result; + } + + /** + * @return int + */ + public function getChunkX() : int{ + return $this->chunkX; + } + + /** + * @return int + */ + public function getChunkZ() : int{ + return $this->chunkZ; + } + + /** + * @return int + */ + public function getSubChunkCount() : int{ + return $this->subChunkCount; + } + + /** + * @return bool + */ + public function isCacheEnabled() : bool{ + return $this->cacheEnabled; + } + + /** + * @return int[] + */ + public function getUsedBlobHashes() : array{ + return $this->usedBlobHashes; + } + + /** + * @return string + */ + public function getExtraPayload() : string{ + return $this->extraPayload; + } + + protected function decodePayload() : void{ + $this->chunkX = $this->getVarInt(); + $this->chunkZ = $this->getVarInt(); + $this->subChunkCount = $this->getUnsignedVarInt(); + $this->cacheEnabled = $this->getBool(); + if($this->cacheEnabled){ + for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){ + $this->usedBlobHashes[] = $this->getLLong(); + } + } + $this->extraPayload = $this->getString(); + } + + protected function encodePayload() : void{ + $this->putVarInt($this->chunkX); + $this->putVarInt($this->chunkZ); + $this->putUnsignedVarInt($this->subChunkCount); + $this->putBool($this->cacheEnabled); + if($this->cacheEnabled){ + $this->putUnsignedVarInt(count($this->usedBlobHashes)); + foreach($this->usedBlobHashes as $hash){ + $this->putLLong($hash); + } + } + $this->putString($this->extraPayload); + } + + public function handle(PacketHandler $handler) : bool{ + return $handler->handleLevelChunk($this); + } +} diff --git a/src/pocketmine/network/mcpe/protocol/FullChunkDataPacket.php b/src/pocketmine/network/mcpe/protocol/LevelEventGenericPacket.php similarity index 53% rename from src/pocketmine/network/mcpe/protocol/FullChunkDataPacket.php rename to src/pocketmine/network/mcpe/protocol/LevelEventGenericPacket.php index f3f2300c2..d462b407e 100644 --- a/src/pocketmine/network/mcpe/protocol/FullChunkDataPacket.php +++ b/src/pocketmine/network/mcpe/protocol/LevelEventGenericPacket.php @@ -25,40 +25,51 @@ namespace pocketmine\network\mcpe\protocol; #include - +use pocketmine\nbt\tag\CompoundTag; +use pocketmine\nbt\TreeRoot; use pocketmine\network\mcpe\handler\PacketHandler; +use pocketmine\network\mcpe\serializer\NetworkNbtSerializer; -class FullChunkDataPacket extends DataPacket implements ClientboundPacket{ - public const NETWORK_ID = ProtocolInfo::FULL_CHUNK_DATA_PACKET; +class LevelEventGenericPacket extends DataPacket implements ClientboundPacket{ + public const NETWORK_ID = ProtocolInfo::LEVEL_EVENT_GENERIC_PACKET; /** @var int */ - public $chunkX; - /** @var int */ - public $chunkZ; - /** @var string */ - public $data; + private $eventId; + /** @var string network-format NBT */ + private $eventData; - public static function create(int $chunkX, int $chunkZ, string $payload) : self{ + public static function create(int $eventId, CompoundTag $data) : self{ $result = new self; - $result->chunkX = $chunkX; - $result->chunkZ = $chunkZ; - $result->data = $payload; + $result->eventId = $eventId; + $result->eventData = (new NetworkNbtSerializer())->write(new TreeRoot($data)); return $result; } + /** + * @return int + */ + public function getEventId() : int{ + return $this->eventId; + } + + /** + * @return string + */ + public function getEventData() : string{ + return $this->eventData; + } + protected function decodePayload() : void{ - $this->chunkX = $this->getVarInt(); - $this->chunkZ = $this->getVarInt(); - $this->data = $this->getString(); + $this->eventId = $this->getVarInt(); + $this->eventData = $this->getRemaining(); } protected function encodePayload() : void{ - $this->putVarInt($this->chunkX); - $this->putVarInt($this->chunkZ); - $this->putString($this->data); + $this->putVarInt($this->eventId); + $this->put($this->eventData); } public function handle(PacketHandler $handler) : bool{ - return $handler->handleFullChunkData($this); + return $handler->handleLevelEventGeneric($this); } } diff --git a/src/pocketmine/network/mcpe/protocol/MoveEntityAbsolutePacket.php b/src/pocketmine/network/mcpe/protocol/MoveActorAbsolutePacket.php similarity index 89% rename from src/pocketmine/network/mcpe/protocol/MoveEntityAbsolutePacket.php rename to src/pocketmine/network/mcpe/protocol/MoveActorAbsolutePacket.php index d0e220e8b..f42a51a9c 100644 --- a/src/pocketmine/network/mcpe/protocol/MoveEntityAbsolutePacket.php +++ b/src/pocketmine/network/mcpe/protocol/MoveActorAbsolutePacket.php @@ -29,8 +29,8 @@ namespace pocketmine\network\mcpe\protocol; use pocketmine\math\Vector3; use pocketmine\network\mcpe\handler\PacketHandler; -class MoveEntityAbsolutePacket extends DataPacket implements ClientboundPacket, ServerboundPacket{ - public const NETWORK_ID = ProtocolInfo::MOVE_ENTITY_ABSOLUTE_PACKET; +class MoveActorAbsolutePacket extends DataPacket implements ClientboundPacket, ServerboundPacket{ + public const NETWORK_ID = ProtocolInfo::MOVE_ACTOR_ABSOLUTE_PACKET; public const FLAG_GROUND = 0x01; public const FLAG_TELEPORT = 0x02; @@ -67,6 +67,6 @@ class MoveEntityAbsolutePacket extends DataPacket implements ClientboundPacket, } public function handle(PacketHandler $handler) : bool{ - return $handler->handleMoveEntityAbsolute($this); + return $handler->handleMoveActorAbsolute($this); } } diff --git a/src/pocketmine/network/mcpe/protocol/MoveEntityDeltaPacket.php b/src/pocketmine/network/mcpe/protocol/MoveActorDeltaPacket.php similarity index 94% rename from src/pocketmine/network/mcpe/protocol/MoveEntityDeltaPacket.php rename to src/pocketmine/network/mcpe/protocol/MoveActorDeltaPacket.php index 0b1851202..7147793e7 100644 --- a/src/pocketmine/network/mcpe/protocol/MoveEntityDeltaPacket.php +++ b/src/pocketmine/network/mcpe/protocol/MoveActorDeltaPacket.php @@ -28,8 +28,8 @@ namespace pocketmine\network\mcpe\protocol; use pocketmine\network\mcpe\handler\PacketHandler; use pocketmine\utils\BinaryDataException; -class MoveEntityDeltaPacket extends DataPacket implements ClientboundPacket{ - public const NETWORK_ID = ProtocolInfo::MOVE_ENTITY_DELTA_PACKET; +class MoveActorDeltaPacket extends DataPacket implements ClientboundPacket{ + public const NETWORK_ID = ProtocolInfo::MOVE_ACTOR_DELTA_PACKET; public const FLAG_HAS_X = 0x01; public const FLAG_HAS_Y = 0x02; @@ -116,6 +116,6 @@ class MoveEntityDeltaPacket extends DataPacket implements ClientboundPacket{ } public function handle(PacketHandler $handler) : bool{ - return $handler->handleMoveEntityDelta($this); + return $handler->handleMoveActorDelta($this); } } diff --git a/src/pocketmine/network/mcpe/protocol/PacketPool.php b/src/pocketmine/network/mcpe/protocol/PacketPool.php index 7c3c5ceda..71748ca91 100644 --- a/src/pocketmine/network/mcpe/protocol/PacketPool.php +++ b/src/pocketmine/network/mcpe/protocol/PacketPool.php @@ -45,11 +45,11 @@ class PacketPool{ static::registerPacket(new SetTimePacket()); static::registerPacket(new StartGamePacket()); static::registerPacket(new AddPlayerPacket()); - static::registerPacket(new AddEntityPacket()); - static::registerPacket(new RemoveEntityPacket()); - static::registerPacket(new AddItemEntityPacket()); - static::registerPacket(new TakeItemEntityPacket()); - static::registerPacket(new MoveEntityAbsolutePacket()); + static::registerPacket(new AddActorPacket()); + static::registerPacket(new RemoveActorPacket()); + static::registerPacket(new AddItemActorPacket()); + static::registerPacket(new TakeItemActorPacket()); + static::registerPacket(new MoveActorAbsolutePacket()); static::registerPacket(new MovePlayerPacket()); static::registerPacket(new RiderJumpPacket()); static::registerPacket(new UpdateBlockPacket()); @@ -58,7 +58,7 @@ class PacketPool{ static::registerPacket(new LevelSoundEventPacketV1()); static::registerPacket(new LevelEventPacket()); static::registerPacket(new BlockEventPacket()); - static::registerPacket(new EntityEventPacket()); + static::registerPacket(new ActorEventPacket()); static::registerPacket(new MobEffectPacket()); static::registerPacket(new UpdateAttributesPacket()); static::registerPacket(new InventoryTransactionPacket()); @@ -66,13 +66,13 @@ class PacketPool{ static::registerPacket(new MobArmorEquipmentPacket()); static::registerPacket(new InteractPacket()); static::registerPacket(new BlockPickRequestPacket()); - static::registerPacket(new EntityPickRequestPacket()); + static::registerPacket(new ActorPickRequestPacket()); static::registerPacket(new PlayerActionPacket()); - static::registerPacket(new EntityFallPacket()); + static::registerPacket(new ActorFallPacket()); static::registerPacket(new HurtArmorPacket()); - static::registerPacket(new SetEntityDataPacket()); - static::registerPacket(new SetEntityMotionPacket()); - static::registerPacket(new SetEntityLinkPacket()); + static::registerPacket(new SetActorDataPacket()); + static::registerPacket(new SetActorMotionPacket()); + static::registerPacket(new SetActorLinkPacket()); static::registerPacket(new SetHealthPacket()); static::registerPacket(new SetSpawnPositionPacket()); static::registerPacket(new AnimatePacket()); @@ -87,9 +87,9 @@ class PacketPool{ static::registerPacket(new CraftingEventPacket()); static::registerPacket(new GuiDataPickItemPacket()); static::registerPacket(new AdventureSettingsPacket()); - static::registerPacket(new BlockEntityDataPacket()); + static::registerPacket(new BlockActorDataPacket()); static::registerPacket(new PlayerInputPacket()); - static::registerPacket(new FullChunkDataPacket()); + static::registerPacket(new LevelChunkPacket()); static::registerPacket(new SetCommandsEnabledPacket()); static::registerPacket(new SetDifficultyPacket()); static::registerPacket(new ChangeDimensionPacket()); @@ -142,22 +142,31 @@ class PacketPool{ static::registerPacket(new SetScorePacket()); static::registerPacket(new LabTablePacket()); static::registerPacket(new UpdateBlockSyncedPacket()); - static::registerPacket(new MoveEntityDeltaPacket()); + static::registerPacket(new MoveActorDeltaPacket()); static::registerPacket(new SetScoreboardIdentityPacket()); static::registerPacket(new SetLocalPlayerAsInitializedPacket()); static::registerPacket(new UpdateSoftEnumPacket()); static::registerPacket(new NetworkStackLatencyPacket()); static::registerPacket(new ScriptCustomEventPacket()); static::registerPacket(new SpawnParticleEffectPacket()); - static::registerPacket(new AvailableEntityIdentifiersPacket()); + static::registerPacket(new AvailableActorIdentifiersPacket()); static::registerPacket(new LevelSoundEventPacketV2()); static::registerPacket(new NetworkChunkPublisherUpdatePacket()); static::registerPacket(new BiomeDefinitionListPacket()); static::registerPacket(new LevelSoundEventPacket()); + static::registerPacket(new LevelEventGenericPacket()); static::registerPacket(new LecternUpdatePacket()); static::registerPacket(new VideoStreamConnectPacket()); - static::registerPacket(new MapCreateLockedCopyPacket()); + static::registerPacket(new AddEntityPacket()); + static::registerPacket(new RemoveEntityPacket()); + static::registerPacket(new ClientCacheStatusPacket()); static::registerPacket(new OnScreenTextureAnimationPacket()); + static::registerPacket(new MapCreateLockedCopyPacket()); + static::registerPacket(new StructureTemplateDataExportRequestPacket()); + static::registerPacket(new StructureTemplateDataExportResponsePacket()); + static::registerPacket(new UpdateBlockPropertiesPacket()); + static::registerPacket(new ClientCacheBlobStatusPacket()); + static::registerPacket(new ClientCacheMissResponsePacket()); } /** diff --git a/src/pocketmine/network/mcpe/protocol/ProtocolInfo.php b/src/pocketmine/network/mcpe/protocol/ProtocolInfo.php index 6488d14a1..152dd4463 100644 --- a/src/pocketmine/network/mcpe/protocol/ProtocolInfo.php +++ b/src/pocketmine/network/mcpe/protocol/ProtocolInfo.php @@ -39,15 +39,15 @@ interface ProtocolInfo{ /** * Actual Minecraft: PE protocol version */ - public const CURRENT_PROTOCOL = 354; + public const CURRENT_PROTOCOL = 361; /** * Current Minecraft PE version reported by the server. This is usually the earliest currently supported version. */ - public const MINECRAFT_VERSION = 'v1.11.0'; + public const MINECRAFT_VERSION = 'v1.12.0'; /** * Version number sent to clients in ping responses. */ - public const MINECRAFT_VERSION_NETWORK = '1.11.0'; + public const MINECRAFT_VERSION_NETWORK = '1.12.0'; public const LOGIN_PACKET = 0x01; public const PLAY_STATUS_PACKET = 0x02; @@ -61,12 +61,12 @@ interface ProtocolInfo{ public const SET_TIME_PACKET = 0x0a; public const START_GAME_PACKET = 0x0b; public const ADD_PLAYER_PACKET = 0x0c; - public const ADD_ENTITY_PACKET = 0x0d; - public const REMOVE_ENTITY_PACKET = 0x0e; - public const ADD_ITEM_ENTITY_PACKET = 0x0f; + public const ADD_ACTOR_PACKET = 0x0d; + public const REMOVE_ACTOR_PACKET = 0x0e; + public const ADD_ITEM_ACTOR_PACKET = 0x0f; - public const TAKE_ITEM_ENTITY_PACKET = 0x11; - public const MOVE_ENTITY_ABSOLUTE_PACKET = 0x12; + public const TAKE_ITEM_ACTOR_PACKET = 0x11; + public const MOVE_ACTOR_ABSOLUTE_PACKET = 0x12; public const MOVE_PLAYER_PACKET = 0x13; public const RIDER_JUMP_PACKET = 0x14; public const UPDATE_BLOCK_PACKET = 0x15; @@ -75,7 +75,7 @@ interface ProtocolInfo{ public const LEVEL_SOUND_EVENT_PACKET_V1 = 0x18; public const LEVEL_EVENT_PACKET = 0x19; public const BLOCK_EVENT_PACKET = 0x1a; - public const ENTITY_EVENT_PACKET = 0x1b; + public const ACTOR_EVENT_PACKET = 0x1b; public const MOB_EFFECT_PACKET = 0x1c; public const UPDATE_ATTRIBUTES_PACKET = 0x1d; public const INVENTORY_TRANSACTION_PACKET = 0x1e; @@ -83,13 +83,13 @@ interface ProtocolInfo{ public const MOB_ARMOR_EQUIPMENT_PACKET = 0x20; public const INTERACT_PACKET = 0x21; public const BLOCK_PICK_REQUEST_PACKET = 0x22; - public const ENTITY_PICK_REQUEST_PACKET = 0x23; + public const ACTOR_PICK_REQUEST_PACKET = 0x23; public const PLAYER_ACTION_PACKET = 0x24; - public const ENTITY_FALL_PACKET = 0x25; + public const ACTOR_FALL_PACKET = 0x25; public const HURT_ARMOR_PACKET = 0x26; - public const SET_ENTITY_DATA_PACKET = 0x27; - public const SET_ENTITY_MOTION_PACKET = 0x28; - public const SET_ENTITY_LINK_PACKET = 0x29; + public const SET_ACTOR_DATA_PACKET = 0x27; + public const SET_ACTOR_MOTION_PACKET = 0x28; + public const SET_ACTOR_LINK_PACKET = 0x29; public const SET_HEALTH_PACKET = 0x2a; public const SET_SPAWN_POSITION_PACKET = 0x2b; public const ANIMATE_PACKET = 0x2c; @@ -104,9 +104,9 @@ interface ProtocolInfo{ public const CRAFTING_EVENT_PACKET = 0x35; public const GUI_DATA_PICK_ITEM_PACKET = 0x36; public const ADVENTURE_SETTINGS_PACKET = 0x37; - public const BLOCK_ENTITY_DATA_PACKET = 0x38; + public const BLOCK_ACTOR_DATA_PACKET = 0x38; public const PLAYER_INPUT_PACKET = 0x39; - public const FULL_CHUNK_DATA_PACKET = 0x3a; + public const LEVEL_CHUNK_PACKET = 0x3a; public const SET_COMMANDS_ENABLED_PACKET = 0x3b; public const SET_DIFFICULTY_PACKET = 0x3c; public const CHANGE_DIMENSION_PACKET = 0x3d; @@ -159,7 +159,7 @@ interface ProtocolInfo{ public const SET_SCORE_PACKET = 0x6c; public const LAB_TABLE_PACKET = 0x6d; public const UPDATE_BLOCK_SYNCED_PACKET = 0x6e; - public const MOVE_ENTITY_DELTA_PACKET = 0x6f; + public const MOVE_ACTOR_DELTA_PACKET = 0x6f; public const SET_SCOREBOARD_IDENTITY_PACKET = 0x70; public const SET_LOCAL_PLAYER_AS_INITIALIZED_PACKET = 0x71; public const UPDATE_SOFT_ENUM_PACKET = 0x72; @@ -167,14 +167,23 @@ interface ProtocolInfo{ public const SCRIPT_CUSTOM_EVENT_PACKET = 0x75; public const SPAWN_PARTICLE_EFFECT_PACKET = 0x76; - public const AVAILABLE_ENTITY_IDENTIFIERS_PACKET = 0x77; + public const AVAILABLE_ACTOR_IDENTIFIERS_PACKET = 0x77; public const LEVEL_SOUND_EVENT_PACKET_V2 = 0x78; public const NETWORK_CHUNK_PUBLISHER_UPDATE_PACKET = 0x79; public const BIOME_DEFINITION_LIST_PACKET = 0x7a; public const LEVEL_SOUND_EVENT_PACKET = 0x7b; - public const LECTERN_UPDATE_PACKET = 0x7c; - public const VIDEO_STREAM_CONNECT_PACKET = 0x7d; - public const MAP_CREATE_LOCKED_COPY_PACKET = 0x7e; - public const ON_SCREEN_TEXTURE_ANIMATION_PACKET = 0x7f; + public const LEVEL_EVENT_GENERIC_PACKET = 0x7c; + public const LECTERN_UPDATE_PACKET = 0x7d; + public const VIDEO_STREAM_CONNECT_PACKET = 0x7e; + public const ADD_ENTITY_PACKET = 0x7f; + public const REMOVE_ENTITY_PACKET = 0x80; + public const CLIENT_CACHE_STATUS_PACKET = 0x81; + public const ON_SCREEN_TEXTURE_ANIMATION_PACKET = 0x82; + public const MAP_CREATE_LOCKED_COPY_PACKET = 0x83; + public const STRUCTURE_TEMPLATE_DATA_EXPORT_REQUEST_PACKET = 0x84; + public const STRUCTURE_TEMPLATE_DATA_EXPORT_RESPONSE_PACKET = 0x85; + public const UPDATE_BLOCK_PROPERTIES_PACKET = 0x86; + public const CLIENT_CACHE_BLOB_STATUS_PACKET = 0x87; + public const CLIENT_CACHE_MISS_RESPONSE_PACKET = 0x88; } diff --git a/src/pocketmine/network/mcpe/protocol/RemoveActorPacket.php b/src/pocketmine/network/mcpe/protocol/RemoveActorPacket.php new file mode 100644 index 000000000..690e5c161 --- /dev/null +++ b/src/pocketmine/network/mcpe/protocol/RemoveActorPacket.php @@ -0,0 +1,54 @@ + + + +use pocketmine\network\mcpe\handler\PacketHandler; + +class RemoveActorPacket extends DataPacket implements ClientboundPacket{ + public const NETWORK_ID = ProtocolInfo::REMOVE_ACTOR_PACKET; + + /** @var int */ + public $entityUniqueId; + + public static function create(int $entityUniqueId) : self{ + $result = new self; + $result->entityUniqueId = $entityUniqueId; + return $result; + } + + protected function decodePayload() : void{ + $this->entityUniqueId = $this->getEntityUniqueId(); + } + + protected function encodePayload() : void{ + $this->putEntityUniqueId($this->entityUniqueId); + } + + public function handle(PacketHandler $handler) : bool{ + return $handler->handleRemoveActor($this); + } +} diff --git a/src/pocketmine/network/mcpe/protocol/RemoveEntityPacket.php b/src/pocketmine/network/mcpe/protocol/RemoveEntityPacket.php index 956a9f063..a4cdf96b4 100644 --- a/src/pocketmine/network/mcpe/protocol/RemoveEntityPacket.php +++ b/src/pocketmine/network/mcpe/protocol/RemoveEntityPacket.php @@ -25,27 +25,33 @@ namespace pocketmine\network\mcpe\protocol; #include - use pocketmine\network\mcpe\handler\PacketHandler; class RemoveEntityPacket extends DataPacket implements ClientboundPacket{ public const NETWORK_ID = ProtocolInfo::REMOVE_ENTITY_PACKET; /** @var int */ - public $entityUniqueId; + private $uvarint1; - public static function create(int $entityUniqueId) : self{ + public static function create(int $uvarint1) : self{ $result = new self; - $result->entityUniqueId = $entityUniqueId; + $result->uvarint1 = $uvarint1; return $result; } + /** + * @return int + */ + public function getUvarint1() : int{ + return $this->uvarint1; + } + protected function decodePayload() : void{ - $this->entityUniqueId = $this->getEntityUniqueId(); + $this->uvarint1 = $this->getUnsignedVarInt(); } protected function encodePayload() : void{ - $this->putEntityUniqueId($this->entityUniqueId); + $this->putUnsignedVarInt($this->uvarint1); } public function handle(PacketHandler $handler) : bool{ diff --git a/src/pocketmine/network/mcpe/protocol/ResourcePackDataInfoPacket.php b/src/pocketmine/network/mcpe/protocol/ResourcePackDataInfoPacket.php index d4f773830..a1ff6baa5 100644 --- a/src/pocketmine/network/mcpe/protocol/ResourcePackDataInfoPacket.php +++ b/src/pocketmine/network/mcpe/protocol/ResourcePackDataInfoPacket.php @@ -42,6 +42,10 @@ class ResourcePackDataInfoPacket extends DataPacket implements ClientboundPacket public $compressedPackSize; /** @var string */ public $sha256; + /** @var bool */ + public $isPremium = false; + /** @var int */ + public $packType = 0; //TODO: check the values for this public static function create(string $packId, int $maxChunkSize, int $chunkCount, int $compressedPackSize, string $sha256sum) : self{ $result = new self; @@ -59,6 +63,8 @@ class ResourcePackDataInfoPacket extends DataPacket implements ClientboundPacket $this->chunkCount = $this->getLInt(); $this->compressedPackSize = $this->getLLong(); $this->sha256 = $this->getString(); + $this->isPremium = $this->getBool(); + $this->packType = $this->getByte(); } protected function encodePayload() : void{ @@ -67,6 +73,8 @@ class ResourcePackDataInfoPacket extends DataPacket implements ClientboundPacket $this->putLInt($this->chunkCount); $this->putLLong($this->compressedPackSize); $this->putString($this->sha256); + $this->putBool($this->isPremium); + $this->putByte($this->packType); } public function handle(PacketHandler $handler) : bool{ diff --git a/src/pocketmine/network/mcpe/protocol/SetEntityDataPacket.php b/src/pocketmine/network/mcpe/protocol/SetActorDataPacket.php similarity index 86% rename from src/pocketmine/network/mcpe/protocol/SetEntityDataPacket.php rename to src/pocketmine/network/mcpe/protocol/SetActorDataPacket.php index 8a329f4c3..308454f57 100644 --- a/src/pocketmine/network/mcpe/protocol/SetEntityDataPacket.php +++ b/src/pocketmine/network/mcpe/protocol/SetActorDataPacket.php @@ -28,8 +28,8 @@ namespace pocketmine\network\mcpe\protocol; use pocketmine\network\mcpe\handler\PacketHandler; -class SetEntityDataPacket extends DataPacket implements ClientboundPacket, ServerboundPacket{ //TODO: check why this is serverbound - public const NETWORK_ID = ProtocolInfo::SET_ENTITY_DATA_PACKET; +class SetActorDataPacket extends DataPacket implements ClientboundPacket, ServerboundPacket{ //TODO: check why this is serverbound + public const NETWORK_ID = ProtocolInfo::SET_ACTOR_DATA_PACKET; /** @var int */ public $entityRuntimeId; @@ -54,6 +54,6 @@ class SetEntityDataPacket extends DataPacket implements ClientboundPacket, Serve } public function handle(PacketHandler $handler) : bool{ - return $handler->handleSetEntityData($this); + return $handler->handleSetActorData($this); } } diff --git a/src/pocketmine/network/mcpe/protocol/SetEntityLinkPacket.php b/src/pocketmine/network/mcpe/protocol/SetActorLinkPacket.php similarity index 86% rename from src/pocketmine/network/mcpe/protocol/SetEntityLinkPacket.php rename to src/pocketmine/network/mcpe/protocol/SetActorLinkPacket.php index d0ddf7054..91b3a91ee 100644 --- a/src/pocketmine/network/mcpe/protocol/SetEntityLinkPacket.php +++ b/src/pocketmine/network/mcpe/protocol/SetActorLinkPacket.php @@ -29,8 +29,8 @@ namespace pocketmine\network\mcpe\protocol; use pocketmine\network\mcpe\handler\PacketHandler; use pocketmine\network\mcpe\protocol\types\EntityLink; -class SetEntityLinkPacket extends DataPacket implements ClientboundPacket{ - public const NETWORK_ID = ProtocolInfo::SET_ENTITY_LINK_PACKET; +class SetActorLinkPacket extends DataPacket implements ClientboundPacket{ + public const NETWORK_ID = ProtocolInfo::SET_ACTOR_LINK_PACKET; /** @var EntityLink */ public $link; @@ -44,6 +44,6 @@ class SetEntityLinkPacket extends DataPacket implements ClientboundPacket{ } public function handle(PacketHandler $handler) : bool{ - return $handler->handleSetEntityLink($this); + return $handler->handleSetActorLink($this); } } diff --git a/src/pocketmine/network/mcpe/protocol/SetEntityMotionPacket.php b/src/pocketmine/network/mcpe/protocol/SetActorMotionPacket.php similarity index 88% rename from src/pocketmine/network/mcpe/protocol/SetEntityMotionPacket.php rename to src/pocketmine/network/mcpe/protocol/SetActorMotionPacket.php index 3901baeac..dae0e6f8a 100644 --- a/src/pocketmine/network/mcpe/protocol/SetEntityMotionPacket.php +++ b/src/pocketmine/network/mcpe/protocol/SetActorMotionPacket.php @@ -32,8 +32,8 @@ use pocketmine\network\mcpe\handler\PacketHandler; /** * TODO: This packet is (erroneously) sent to the server when the client is riding a vehicle. */ -class SetEntityMotionPacket extends DataPacket implements ClientboundPacket, GarbageServerboundPacket{ - public const NETWORK_ID = ProtocolInfo::SET_ENTITY_MOTION_PACKET; +class SetActorMotionPacket extends DataPacket implements ClientboundPacket, GarbageServerboundPacket{ + public const NETWORK_ID = ProtocolInfo::SET_ACTOR_MOTION_PACKET; /** @var int */ public $entityRuntimeId; @@ -58,6 +58,6 @@ class SetEntityMotionPacket extends DataPacket implements ClientboundPacket, Gar } public function handle(PacketHandler $handler) : bool{ - return $handler->handleSetEntityMotion($this); + return $handler->handleSetActorMotion($this); } } diff --git a/src/pocketmine/network/mcpe/protocol/StartGamePacket.php b/src/pocketmine/network/mcpe/protocol/StartGamePacket.php index caa24d08c..7bc418712 100644 --- a/src/pocketmine/network/mcpe/protocol/StartGamePacket.php +++ b/src/pocketmine/network/mcpe/protocol/StartGamePacket.php @@ -32,12 +32,17 @@ use pocketmine\network\mcpe\protocol\types\PlayerPermissions; use pocketmine\network\mcpe\protocol\types\RuntimeBlockMapping; use pocketmine\network\mcpe\serializer\NetworkBinaryStream; use function count; +use function file_get_contents; +use function json_decode; +use const pocketmine\RESOURCE_PATH; class StartGamePacket extends DataPacket implements ClientboundPacket{ public const NETWORK_ID = ProtocolInfo::START_GAME_PACKET; /** @var string|null */ - private static $runtimeIdTableCache; + private static $blockTableCache = null; + /** @var string|null */ + private static $itemTableCache = null; /** @var int */ public $entityUniqueId; @@ -122,6 +127,8 @@ class StartGamePacket extends DataPacket implements ClientboundPacket{ public $isFromWorldTemplate = false; /** @var bool */ public $isWorldTemplateOptionLocked = false; + /** @var bool */ + public $onlySpawnV1Villagers = false; /** @var string */ public $levelId = ""; //base64 string, usually the same as world folder name in vanilla @@ -138,11 +145,10 @@ class StartGamePacket extends DataPacket implements ClientboundPacket{ /** @var string */ public $multiplayerCorrelationId = ""; //TODO: this should be filled with a UUID of some sort - /** @var bool */ - public $onlySpawnV1Villagers = false; - - /** @var array|null each entry must have a "name" (string) and "data" (int16) element */ - public $runtimeIdTable = null; + /** @var array|null ["name" (string), "data" (int16), "legacy_id" (int16)] */ + public $blockTable = null; + /** @var array|null string (name) => int16 (legacyID) */ + public $itemTable = null; protected function decodePayload() : void{ $this->entityUniqueId = $this->getEntityUniqueId(); @@ -185,6 +191,7 @@ class StartGamePacket extends DataPacket implements ClientboundPacket{ $this->useMsaGamertagsOnly = $this->getBool(); $this->isFromWorldTemplate = $this->getBool(); $this->isWorldTemplateOptionLocked = $this->getBool(); + $this->onlySpawnV1Villagers = $this->getBool(); $this->levelId = $this->getString(); $this->worldName = $this->getString(); @@ -194,18 +201,23 @@ class StartGamePacket extends DataPacket implements ClientboundPacket{ $this->enchantmentSeed = $this->getVarInt(); - $count = $this->getUnsignedVarInt(); - $table = []; - for($i = 0; $i < $count; ++$i){ + $this->blockTable = []; + for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){ $id = $this->getString(); - $data = $this->getLShort(); + $data = $this->getSignedLShort(); + $unknown = $this->getSignedLShort(); - $table[$i] = ["name" => $id, "data" => $data]; + $this->blockTable[$i] = ["name" => $id, "data" => $data, "legacy_id" => $unknown]; + } + $this->itemTable = []; + for($i = 0, $count = $this->getUnsignedVarInt(); $i < $count; ++$i){ + $id = $this->getString(); + $legacyId = $this->getSignedLShort(); + + $this->itemTable[$id] = $legacyId; } - $this->runtimeIdTable = $table; $this->multiplayerCorrelationId = $this->getString(); - $this->onlySpawnV1Villagers = $this->getBool(); } protected function encodePayload() : void{ @@ -249,6 +261,7 @@ class StartGamePacket extends DataPacket implements ClientboundPacket{ $this->putBool($this->useMsaGamertagsOnly); $this->putBool($this->isFromWorldTemplate); $this->putBool($this->isWorldTemplateOptionLocked); + $this->putBool($this->onlySpawnV1Villagers); $this->putString($this->levelId); $this->putString($this->worldName); @@ -258,18 +271,25 @@ class StartGamePacket extends DataPacket implements ClientboundPacket{ $this->putVarInt($this->enchantmentSeed); - if($this->runtimeIdTable === null){ - if(self::$runtimeIdTableCache === null){ + if($this->blockTable === null){ + if(self::$blockTableCache === null){ //this is a really nasty hack, but it'll do for now - self::$runtimeIdTableCache = self::serializeBlockTable(RuntimeBlockMapping::getBedrockKnownStates()); + self::$blockTableCache = self::serializeBlockTable(RuntimeBlockMapping::getBedrockKnownStates()); } - $this->put(self::$runtimeIdTableCache); + $this->put(self::$blockTableCache); }else{ - $this->put(self::serializeBlockTable($this->runtimeIdTable)); + $this->put(self::serializeBlockTable($this->blockTable)); + } + if($this->itemTable === null){ + if(self::$itemTableCache === null){ + self::$itemTableCache = self::serializeItemTable(json_decode(file_get_contents(RESOURCE_PATH . '/vanilla/item_id_map.json'), true)); + } + $this->put(self::$itemTableCache); + }else{ + $this->put(self::serializeItemTable($this->itemTable)); } $this->putString($this->multiplayerCorrelationId); - $this->putBool($this->onlySpawnV1Villagers); } private static function serializeBlockTable(array $table) : string{ @@ -278,6 +298,17 @@ class StartGamePacket extends DataPacket implements ClientboundPacket{ foreach($table as $v){ $stream->putString($v["name"]); $stream->putLShort($v["data"]); + $stream->putLShort($v["legacy_id"]); + } + return $stream->getBuffer(); + } + + private static function serializeItemTable(array $table) : string{ + $stream = new NetworkBinaryStream(); + $stream->putUnsignedVarInt(count($table)); + foreach($table as $name => $legacyId){ + $stream->putString($name); + $stream->putLShort($legacyId); } return $stream->getBuffer(); } diff --git a/src/pocketmine/network/mcpe/protocol/StructureTemplateDataExportRequestPacket.php b/src/pocketmine/network/mcpe/protocol/StructureTemplateDataExportRequestPacket.php new file mode 100644 index 000000000..e3816a454 --- /dev/null +++ b/src/pocketmine/network/mcpe/protocol/StructureTemplateDataExportRequestPacket.php @@ -0,0 +1,44 @@ + + +use pocketmine\network\mcpe\handler\PacketHandler; + +class StructureTemplateDataExportRequestPacket extends DataPacket implements ServerboundPacket{ + public const NETWORK_ID = ProtocolInfo::STRUCTURE_TEMPLATE_DATA_EXPORT_REQUEST_PACKET; + + protected function decodePayload() : void{ + //TODO + } + + protected function encodePayload() : void{ + //TODO + } + + public function handle(PacketHandler $handler) : bool{ + return $handler->handleStructureTemplateDataExportRequest($this); + } +} diff --git a/src/pocketmine/network/mcpe/protocol/StructureTemplateDataExportResponsePacket.php b/src/pocketmine/network/mcpe/protocol/StructureTemplateDataExportResponsePacket.php new file mode 100644 index 000000000..baeac7673 --- /dev/null +++ b/src/pocketmine/network/mcpe/protocol/StructureTemplateDataExportResponsePacket.php @@ -0,0 +1,44 @@ + + +use pocketmine\network\mcpe\handler\PacketHandler; + +class StructureTemplateDataExportResponsePacket extends DataPacket implements ClientboundPacket{ + public const NETWORK_ID = ProtocolInfo::STRUCTURE_TEMPLATE_DATA_EXPORT_RESPONSE_PACKET; + + protected function decodePayload() : void{ + //TODO + } + + protected function encodePayload() : void{ + //TODO + } + + public function handle(PacketHandler $handler) : bool{ + return $handler->handleStructureTemplateDataExportResponse($this); + } +} diff --git a/src/pocketmine/network/mcpe/protocol/TakeItemEntityPacket.php b/src/pocketmine/network/mcpe/protocol/TakeItemActorPacket.php similarity index 88% rename from src/pocketmine/network/mcpe/protocol/TakeItemEntityPacket.php rename to src/pocketmine/network/mcpe/protocol/TakeItemActorPacket.php index bc1ff36ae..36dd8fa62 100644 --- a/src/pocketmine/network/mcpe/protocol/TakeItemEntityPacket.php +++ b/src/pocketmine/network/mcpe/protocol/TakeItemActorPacket.php @@ -28,8 +28,8 @@ namespace pocketmine\network\mcpe\protocol; use pocketmine\network\mcpe\handler\PacketHandler; -class TakeItemEntityPacket extends DataPacket implements ClientboundPacket{ - public const NETWORK_ID = ProtocolInfo::TAKE_ITEM_ENTITY_PACKET; +class TakeItemActorPacket extends DataPacket implements ClientboundPacket{ + public const NETWORK_ID = ProtocolInfo::TAKE_ITEM_ACTOR_PACKET; /** @var int */ public $target; @@ -54,6 +54,6 @@ class TakeItemEntityPacket extends DataPacket implements ClientboundPacket{ } public function handle(PacketHandler $handler) : bool{ - return $handler->handleTakeItemEntity($this); + return $handler->handleTakeItemActor($this); } } diff --git a/src/pocketmine/network/mcpe/protocol/UpdateBlockPropertiesPacket.php b/src/pocketmine/network/mcpe/protocol/UpdateBlockPropertiesPacket.php new file mode 100644 index 000000000..f0f1d41f4 --- /dev/null +++ b/src/pocketmine/network/mcpe/protocol/UpdateBlockPropertiesPacket.php @@ -0,0 +1,56 @@ + + +use pocketmine\nbt\tag\CompoundTag; +use pocketmine\nbt\TreeRoot; +use pocketmine\network\mcpe\handler\PacketHandler; +use pocketmine\network\mcpe\serializer\NetworkNbtSerializer; + +class UpdateBlockPropertiesPacket extends DataPacket implements ClientboundPacket{ + public const NETWORK_ID = ProtocolInfo::UPDATE_BLOCK_PROPERTIES_PACKET; + + /** @var string */ + private $nbt; + + public static function create(CompoundTag $data) : self{ + $result = new self; + $result->nbt = (new NetworkNbtSerializer())->write(new TreeRoot($data)); + return $result; + } + + protected function decodePayload() : void{ + $this->nbt = $this->getRemaining(); + } + + protected function encodePayload() : void{ + $this->put($this->nbt); + } + + public function handle(PacketHandler $handler) : bool{ + return $handler->handleUpdateBlockProperties($this); + } +} diff --git a/src/pocketmine/network/mcpe/protocol/VideoStreamConnectPacket.php b/src/pocketmine/network/mcpe/protocol/VideoStreamConnectPacket.php index 4059579ee..ba7f643bf 100644 --- a/src/pocketmine/network/mcpe/protocol/VideoStreamConnectPacket.php +++ b/src/pocketmine/network/mcpe/protocol/VideoStreamConnectPacket.php @@ -39,17 +39,25 @@ class VideoStreamConnectPacket extends DataPacket implements ClientboundPacket{ public $frameSendFrequency; /** @var int */ public $action; + /** @var int */ + public $resolutionX; + /** @var int */ + public $resolutionY; protected function decodePayload() : void{ $this->serverUri = $this->getString(); $this->frameSendFrequency = $this->getLFloat(); $this->action = $this->getByte(); + $this->resolutionX = $this->getLInt(); + $this->resolutionY = $this->getLInt(); } protected function encodePayload() : void{ $this->putString($this->serverUri); $this->putLFloat($this->frameSendFrequency); $this->putByte($this->action); + $this->putLInt($this->resolutionX); + $this->putLInt($this->resolutionY); } public function handle(PacketHandler $handler) : bool{ diff --git a/src/pocketmine/network/mcpe/protocol/types/ChunkCacheBlob.php b/src/pocketmine/network/mcpe/protocol/types/ChunkCacheBlob.php new file mode 100644 index 000000000..acf09f35f --- /dev/null +++ b/src/pocketmine/network/mcpe/protocol/types/ChunkCacheBlob.php @@ -0,0 +1,56 @@ +hash = $hash; + $this->payload = $payload; + } + + /** + * @return int + */ + public function getHash() : int{ + return $this->hash; + } + + /** + * @return string + */ + public function getPayload() : string{ + return $this->payload; + } +} diff --git a/src/pocketmine/network/mcpe/protocol/types/EntityMetadataProperties.php b/src/pocketmine/network/mcpe/protocol/types/EntityMetadataProperties.php index 910fb1968..7318f118f 100644 --- a/src/pocketmine/network/mcpe/protocol/types/EntityMetadataProperties.php +++ b/src/pocketmine/network/mcpe/protocol/types/EntityMetadataProperties.php @@ -76,68 +76,74 @@ final class EntityMetadataProperties{ public const LEAD_HOLDER_EID = 37; //long public const SCALE = 38; //float public const HAS_NPC_COMPONENT = 39; //byte (???) - public const SKIN_ID = 40; //string - public const NPC_SKIN_ID = 41; //string - public const URL_TAG = 42; //string - public const MAX_AIR = 43; //short - public const MARK_VARIANT = 44; //int - public const CONTAINER_TYPE = 45; //byte (ContainerComponent) - public const CONTAINER_BASE_SIZE = 46; //int (ContainerComponent) - public const CONTAINER_EXTRA_SLOTS_PER_STRENGTH = 47; //int (used for llamas, inventory size is baseSize + thisProp * strength) - public const BLOCK_TARGET = 48; //block coords (ender crystal) - public const WITHER_INVULNERABLE_TICKS = 49; //int - public const WITHER_TARGET_1 = 50; //long - public const WITHER_TARGET_2 = 51; //long - public const WITHER_TARGET_3 = 52; //long - /* 53 (short) */ - public const BOUNDING_BOX_WIDTH = 54; //float - public const BOUNDING_BOX_HEIGHT = 55; //float - public const FUSE_LENGTH = 56; //int - public const RIDER_SEAT_POSITION = 57; //vector3f - public const RIDER_ROTATION_LOCKED = 58; //byte - public const RIDER_MAX_ROTATION = 59; //float - public const RIDER_MIN_ROTATION = 60; //float - public const AREA_EFFECT_CLOUD_RADIUS = 61; //float - public const AREA_EFFECT_CLOUD_WAITING = 62; //int - public const AREA_EFFECT_CLOUD_PARTICLE_ID = 63; //int - /* 64 (int) shulker-related */ - public const SHULKER_ATTACH_FACE = 65; //byte - /* 66 (short) shulker-related */ - public const SHULKER_ATTACH_POS = 67; //block coords - public const TRADING_PLAYER_EID = 68; //long + public const NPC_SKIN_INDEX = 40; //string + public const NPC_ACTIONS = 41; //string (maybe JSON blob?) + public const MAX_AIR = 42; //short + public const MARK_VARIANT = 43; //int + public const CONTAINER_TYPE = 44; //byte (ContainerComponent) + public const CONTAINER_BASE_SIZE = 45; //int (ContainerComponent) + public const CONTAINER_EXTRA_SLOTS_PER_STRENGTH = 46; //int (used for llamas, inventory size is baseSize + thisProp * strength) + public const BLOCK_TARGET = 47; //block coords (ender crystal) + public const WITHER_INVULNERABLE_TICKS = 48; //int + public const WITHER_TARGET_1 = 49; //long + public const WITHER_TARGET_2 = 50; //long + public const WITHER_TARGET_3 = 51; //long + /* 52 (short) */ + public const BOUNDING_BOX_WIDTH = 53; //float + public const BOUNDING_BOX_HEIGHT = 54; //float + public const FUSE_LENGTH = 55; //int + public const RIDER_SEAT_POSITION = 56; //vector3f + public const RIDER_ROTATION_LOCKED = 57; //byte + public const RIDER_MAX_ROTATION = 58; //float + public const RIDER_MIN_ROTATION = 59; //float + public const AREA_EFFECT_CLOUD_RADIUS = 60; //float + public const AREA_EFFECT_CLOUD_WAITING = 61; //int + public const AREA_EFFECT_CLOUD_PARTICLE_ID = 62; //int + /* 63 (int) shulker-related */ + public const SHULKER_ATTACH_FACE = 64; //byte + /* 65 (short) shulker-related */ + public const SHULKER_ATTACH_POS = 66; //block coords + public const TRADING_PLAYER_EID = 67; //long - /* 70 (byte) command-block */ - public const COMMAND_BLOCK_COMMAND = 71; //string - public const COMMAND_BLOCK_LAST_OUTPUT = 72; //string - public const COMMAND_BLOCK_TRACK_OUTPUT = 73; //byte - public const CONTROLLING_RIDER_SEAT_NUMBER = 74; //byte - public const STRENGTH = 75; //int - public const MAX_STRENGTH = 76; //int - /* 77 (int) */ - public const LIMITED_LIFE = 78; - public const ARMOR_STAND_POSE_INDEX = 79; //int - public const ENDER_CRYSTAL_TIME_OFFSET = 80; //int - public const ALWAYS_SHOW_NAMETAG = 81; //byte: -1 = default, 0 = only when looked at, 1 = always - public const COLOR_2 = 82; //byte - /* 83 (unknown) */ - public const SCORE_TAG = 84; //string - public const BALLOON_ATTACHED_ENTITY = 85; //int64, entity unique ID of owner - public const PUFFERFISH_SIZE = 86; //byte - public const BOAT_BUBBLE_TIME = 87; //int (time in bubble column) - public const PLAYER_AGENT_EID = 88; //long - /* 89 (float) related to panda sitting - * 90 (float) related to panda sitting */ - public const EAT_COUNTER = 91; //int (used by pandas) - public const FLAGS2 = 92; //long (extended data flags) - /* 93 (float) related to panda lying down - * 94 (float) related to panda lying down */ - public const AREA_EFFECT_CLOUD_DURATION = 95; //int - public const AREA_EFFECT_CLOUD_SPAWN_TIME = 96; //int - public const AREA_EFFECT_CLOUD_RADIUS_PER_TICK = 97; //float, usually negative - public const AREA_EFFECT_CLOUD_RADIUS_CHANGE_ON_PICKUP = 98; //float - public const AREA_EFFECT_CLOUD_PICKUP_COUNT = 99; //int - public const INTERACTIVE_TAG = 100; //string (button text) - public const TRADE_TIER = 101; //int - public const MAX_TRADE_TIER = 102; //int - public const TRADE_XP = 103; //int + /* 69 (byte) command-block */ + public const COMMAND_BLOCK_COMMAND = 70; //string + public const COMMAND_BLOCK_LAST_OUTPUT = 71; //string + public const COMMAND_BLOCK_TRACK_OUTPUT = 72; //byte + public const CONTROLLING_RIDER_SEAT_NUMBER = 73; //byte + public const STRENGTH = 74; //int + public const MAX_STRENGTH = 75; //int + /* 76 (int) */ + public const LIMITED_LIFE = 77; + public const ARMOR_STAND_POSE_INDEX = 78; //int + public const ENDER_CRYSTAL_TIME_OFFSET = 79; //int + public const ALWAYS_SHOW_NAMETAG = 80; //byte: -1 = default, 0 = only when looked at, 1 = always + public const COLOR_2 = 81; //byte + /* 82 (unknown) */ + public const SCORE_TAG = 83; //string + public const BALLOON_ATTACHED_ENTITY = 84; //int64, entity unique ID of owner + public const PUFFERFISH_SIZE = 85; //byte + public const BOAT_BUBBLE_TIME = 86; //int (time in bubble column) + public const PLAYER_AGENT_EID = 87; //long + /* 88 (float) related to panda sitting + * 89 (float) related to panda sitting */ + public const EAT_COUNTER = 90; //int (used by pandas) + public const FLAGS2 = 91; //long (extended data flags) + /* 92 (float) related to panda lying down + * 93 (float) related to panda lying down */ + public const AREA_EFFECT_CLOUD_DURATION = 94; //int + public const AREA_EFFECT_CLOUD_SPAWN_TIME = 95; //int + public const AREA_EFFECT_CLOUD_RADIUS_PER_TICK = 96; //float, usually negative + public const AREA_EFFECT_CLOUD_RADIUS_CHANGE_ON_PICKUP = 97; //float + public const AREA_EFFECT_CLOUD_PICKUP_COUNT = 98; //int + public const INTERACTIVE_TAG = 99; //string (button text) + public const TRADE_TIER = 100; //int + public const MAX_TRADE_TIER = 101; //int + public const TRADE_XP = 102; //int + public const SKIN_ID = 103; //int ??? + /* 104 (int) related to wither */ + public const COMMAND_BLOCK_TICK_DELAY = 105; //int + public const COMMAND_BLOCK_EXECUTE_ON_FIRST_TICK = 106; //byte + public const AMBIENT_SOUND_INTERVAL_MIN = 107; //float + public const AMBIENT_SOUND_INTERVAL_RANGE = 108; //float + public const AMBIENT_SOUND_EVENT = 109; //string } diff --git a/src/pocketmine/network/mcpe/protocol/types/RuntimeBlockMapping.php b/src/pocketmine/network/mcpe/protocol/types/RuntimeBlockMapping.php index ba1a14e6b..ae1432792 100644 --- a/src/pocketmine/network/mcpe/protocol/types/RuntimeBlockMapping.php +++ b/src/pocketmine/network/mcpe/protocol/types/RuntimeBlockMapping.php @@ -56,9 +56,11 @@ final class RuntimeBlockMapping{ foreach($compressedTable as $prefix => $entries){ foreach($entries as $shortStringId => $states){ foreach($states as $state){ + $name = "$prefix:$shortStringId"; $decompressed[] = [ - "name" => "$prefix:$shortStringId", - "data" => $state + "name" => $name, + "data" => $state, + "legacy_id" => $legacyIdMap[$name] ]; } } @@ -66,11 +68,12 @@ final class RuntimeBlockMapping{ self::$bedrockKnownStates = self::randomizeTable($decompressed); foreach(self::$bedrockKnownStates as $k => $obj){ - //this has to use the json offset to make sure the mapping is consistent with what we send over network, even though we aren't using all the entries - if(!isset($legacyIdMap[$obj["name"]])){ + if($obj["data"] > 15){ + //TODO: in 1.12 they started using data values bigger than 4 bits which we can't handle right now continue; } - self::registerMapping($k, $legacyIdMap[$obj["name"]], $obj["data"]); + //this has to use the json offset to make sure the mapping is consistent with what we send over network, even though we aren't using all the entries + self::registerMapping($k, $obj["legacy_id"], $obj["data"]); } } diff --git a/src/pocketmine/network/mcpe/serializer/ChunkSerializer.php b/src/pocketmine/network/mcpe/serializer/ChunkSerializer.php index e95f5b0c0..db4258bdf 100644 --- a/src/pocketmine/network/mcpe/serializer/ChunkSerializer.php +++ b/src/pocketmine/network/mcpe/serializer/ChunkSerializer.php @@ -28,7 +28,6 @@ use pocketmine\network\mcpe\protocol\types\RuntimeBlockMapping; use pocketmine\utils\BinaryStream; use pocketmine\world\format\Chunk; use function count; -use function pack; final class ChunkSerializer{ @@ -46,8 +45,6 @@ final class ChunkSerializer{ public static function serialize(Chunk $chunk, ?string $tiles = null) : string{ $stream = new NetworkBinaryStream(); $subChunkCount = $chunk->getSubChunkSendCount(); - $stream->putByte($subChunkCount); - for($y = 0; $y < $subChunkCount; ++$y){ $layers = $chunk->getSubChunk($y)->getBlockLayers(); $stream->putByte(8); //version @@ -64,7 +61,6 @@ final class ChunkSerializer{ } } } - $stream->put(pack("v*", ...$chunk->getHeightMapArray())); $stream->put($chunk->getBiomeIdArray()); $stream->putByte(0); //border block array count //Border block entry format: 1 byte (4 bits X, 4 bits Z). These are however useless since they crash the regular client. diff --git a/src/pocketmine/network/mcpe/serializer/NetworkBinaryStream.php b/src/pocketmine/network/mcpe/serializer/NetworkBinaryStream.php index 725fcb23e..a9eabe378 100644 --- a/src/pocketmine/network/mcpe/serializer/NetworkBinaryStream.php +++ b/src/pocketmine/network/mcpe/serializer/NetworkBinaryStream.php @@ -26,12 +26,14 @@ namespace pocketmine\network\mcpe\serializer; #include use pocketmine\entity\Attribute; +use pocketmine\item\Durable; use pocketmine\item\Item; use pocketmine\item\ItemFactory; use pocketmine\item\ItemIds; use pocketmine\math\Vector3; use pocketmine\nbt\NbtDataException; use pocketmine\nbt\tag\CompoundTag; +use pocketmine\nbt\tag\IntTag; use pocketmine\nbt\TreeRoot; use pocketmine\network\BadPacketException; use pocketmine\network\mcpe\protocol\types\CommandOriginData; @@ -45,6 +47,9 @@ use function strlen; class NetworkBinaryStream extends BinaryStream{ + private const DAMAGE_TAG = "Damage"; //TAG_Int + private const DAMAGE_TAG_CONFLICT_RESOLUTION = "___Damage_ProtocolCollisionResolution___"; + /** * @return string * @throws BinaryDataException @@ -93,12 +98,10 @@ class NetworkBinaryStream extends BinaryStream{ $auxValue = $this->getVarInt(); $data = $auxValue >> 8; - if($data === 0x7fff){ - $data = -1; - } $cnt = $auxValue & 0xff; $nbtLen = $this->getLShort(); + /** @var CompoundTag|null $compound */ $compound = null; if($nbtLen === 0xffff){ @@ -129,6 +132,21 @@ class NetworkBinaryStream extends BinaryStream{ $this->getVarLong(); //"blocking tick" (ffs mojang) } + if($compound !== null){ + if($compound->hasTag(self::DAMAGE_TAG, IntTag::class)){ + $data = $compound->getInt(self::DAMAGE_TAG); + $compound->removeTag(self::DAMAGE_TAG); + if($compound->count() === 0){ + $compound = null; + goto end; + } + } + if(($conflicted = $compound->getTag(self::DAMAGE_TAG_CONFLICT_RESOLUTION)) !== null){ + $compound->removeTag(self::DAMAGE_TAG_CONFLICT_RESOLUTION); + $compound->setTag(self::DAMAGE_TAG, $conflicted); + } + } + end: try{ return ItemFactory::get($id, $data, $cnt, $compound); }catch(\InvalidArgumentException $e){ @@ -148,10 +166,26 @@ class NetworkBinaryStream extends BinaryStream{ $auxValue = (($item->getMeta() & 0x7fff) << 8) | $item->getCount(); $this->putVarInt($auxValue); + $nbt = null; if($item->hasNamedTag()){ + $nbt = clone $item->getNamedTag(); + } + if($item instanceof Durable and $item->getDamage() > 0){ + if($nbt !== null){ + if(($existing = $nbt->getTag(self::DAMAGE_TAG)) !== null){ + $nbt->removeTag(self::DAMAGE_TAG); + $nbt->setTag(self::DAMAGE_TAG_CONFLICT_RESOLUTION, $existing); + } + }else{ + $nbt = new CompoundTag(); + } + $nbt->setInt(self::DAMAGE_TAG, $item->getDamage()); + } + + if($nbt !== null){ $this->putLShort(0xffff); $this->putByte(1); //TODO: some kind of count field? always 1 as of 1.9.0 - $this->put((new NetworkNbtSerializer())->write(new TreeRoot($item->getNamedTag()))); + $this->put((new NetworkNbtSerializer())->write(new TreeRoot($nbt))); }else{ $this->putLShort(0); } @@ -164,6 +198,29 @@ class NetworkBinaryStream extends BinaryStream{ } } + public function getRecipeIngredient() : Item{ + $id = $this->getVarInt(); + if($id === 0){ + return ItemFactory::get(ItemIds::AIR, 0, 0); + } + $meta = $this->getVarInt(); + if($meta === 0x7fff){ + $meta = -1; + } + $count = $this->getVarInt(); + return ItemFactory::get($id, $meta, $count); + } + + public function putRecipeIngredient(Item $item) : void{ + if($item->isNull()){ + $this->putVarInt(0); + }else{ + $this->putVarInt($item->getId()); + $this->putVarInt($item->getMeta() & 0x7fff); + $this->putVarInt($item->getCount()); + } + } + /** * Decodes entity metadata from the stream. * diff --git a/src/pocketmine/player/Player.php b/src/pocketmine/player/Player.php index 467e73927..fca68a01d 100644 --- a/src/pocketmine/player/Player.php +++ b/src/pocketmine/player/Player.php @@ -84,9 +84,9 @@ use pocketmine\nbt\tag\DoubleTag; use pocketmine\nbt\tag\IntTag; use pocketmine\nbt\tag\ListTag; use pocketmine\network\mcpe\NetworkSession; +use pocketmine\network\mcpe\protocol\ActorEventPacket; use pocketmine\network\mcpe\protocol\AnimatePacket; use pocketmine\network\mcpe\protocol\ClientboundPacket; -use pocketmine\network\mcpe\protocol\EntityEventPacket; use pocketmine\network\mcpe\protocol\LevelEventPacket; use pocketmine\network\mcpe\protocol\MovePlayerPacket; use pocketmine\network\mcpe\protocol\SetTitlePacket; @@ -1760,7 +1760,7 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, if($ev->isCancelled()){ return false; } - $this->broadcastEntityEvent(EntityEventPacket::ARM_SWING, null, $this->getViewers()); + $this->broadcastEntityEvent(ActorEventPacket::ARM_SWING, null, $this->getViewers()); if($target->onAttack($this->inventory->getItemInHand(), $face, $this)){ return true; } @@ -1785,7 +1785,7 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, public function continueBreakBlock(Vector3 $pos, int $face) : void{ $block = $this->world->getBlock($pos); $this->world->addParticle($pos, new PunchBlockParticle($block, $face)); - $this->broadcastEntityEvent(EntityEventPacket::ARM_SWING, null, $this->getViewers()); + $this->broadcastEntityEvent(ActorEventPacket::ARM_SWING, null, $this->getViewers()); //TODO: destroy-progress level event } @@ -1805,7 +1805,7 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, $this->doCloseInventory(); if($this->canInteract($pos->add(0.5, 0.5, 0.5), $this->isCreative() ? 13 : 7) and !$this->isSpectator()){ - $this->broadcastEntityEvent(EntityEventPacket::ARM_SWING, null, $this->getViewers()); + $this->broadcastEntityEvent(ActorEventPacket::ARM_SWING, null, $this->getViewers()); $item = $this->inventory->getItemInHand(); $oldItem = clone $item; if($this->world->useBreakOn($pos, $item, $this, true)){ @@ -1833,7 +1833,7 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, $this->setUsingItem(false); if($this->canInteract($pos->add(0.5, 0.5, 0.5), 13) and !$this->isSpectator()){ - $this->broadcastEntityEvent(EntityEventPacket::ARM_SWING, null, $this->getViewers()); + $this->broadcastEntityEvent(ActorEventPacket::ARM_SWING, null, $this->getViewers()); $item = $this->inventory->getItemInHand(); //this is a copy of the real item $oldItem = clone $item; if($this->world->useItemOn($pos, $item, $face, $clickOffset, $this, true)){ @@ -1893,7 +1893,7 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, if($ev->isCancelled()){ return false; } - $this->broadcastEntityEvent(EntityEventPacket::ARM_SWING, null, $this->getViewers()); + $this->broadcastEntityEvent(ActorEventPacket::ARM_SWING, null, $this->getViewers()); if($ev->getModifier(EntityDamageEvent::MODIFIER_CRITICAL) > 0){ $entity->broadcastAnimation(null, AnimatePacket::ACTION_CRITICAL_HIT); @@ -1970,7 +1970,7 @@ class Player extends Human implements CommandSender, ChunkLoader, ChunkListener, * @param Item $item */ public function dropItem(Item $item) : void{ - $this->broadcastEntityEvent(EntityEventPacket::ARM_SWING, null, $this->getViewers()); + $this->broadcastEntityEvent(ActorEventPacket::ARM_SWING, null, $this->getViewers()); $this->world->dropItem($this->add(0, 1.3, 0), $item, $this->getDirectionVector()->multiply(0.4), 40); } diff --git a/src/pocketmine/world/World.php b/src/pocketmine/world/World.php index d5417ee05..cfcc15f6a 100644 --- a/src/pocketmine/world/World.php +++ b/src/pocketmine/world/World.php @@ -53,7 +53,7 @@ use pocketmine\math\AxisAlignedBB; use pocketmine\math\Vector3; use pocketmine\nbt\tag\ListTag; use pocketmine\nbt\tag\StringTag; -use pocketmine\network\mcpe\protocol\BlockEntityDataPacket; +use pocketmine\network\mcpe\protocol\BlockActorDataPacket; use pocketmine\network\mcpe\protocol\ClientboundPacket; use pocketmine\network\mcpe\protocol\LevelEventPacket; use pocketmine\network\mcpe\protocol\SetDifficultyPacket; @@ -902,7 +902,7 @@ class World implements ChunkManager{ $tile = $this->getTileAt($b->x, $b->y, $b->z); if($tile instanceof Spawnable){ - $packets[] = BlockEntityDataPacket::create($tile->x, $tile->y, $tile->z, $tile->getSerializedSpawnCompound()); + $packets[] = BlockActorDataPacket::create($tile->x, $tile->y, $tile->z, $tile->getSerializedSpawnCompound()); } } diff --git a/src/pocketmine/world/particle/FloatingTextParticle.php b/src/pocketmine/world/particle/FloatingTextParticle.php index 02ea68a3f..5ad9d78d3 100644 --- a/src/pocketmine/world/particle/FloatingTextParticle.php +++ b/src/pocketmine/world/particle/FloatingTextParticle.php @@ -29,7 +29,7 @@ use pocketmine\item\ItemFactory; use pocketmine\math\Vector3; use pocketmine\network\mcpe\protocol\AddPlayerPacket; use pocketmine\network\mcpe\protocol\PlayerListPacket; -use pocketmine\network\mcpe\protocol\RemoveEntityPacket; +use pocketmine\network\mcpe\protocol\RemoveActorPacket; use pocketmine\network\mcpe\protocol\types\EntityMetadataFlags; use pocketmine\network\mcpe\protocol\types\EntityMetadataProperties; use pocketmine\network\mcpe\protocol\types\EntityMetadataTypes; @@ -84,7 +84,7 @@ class FloatingTextParticle implements Particle{ if($this->entityId === null){ $this->entityId = EntityFactory::nextRuntimeId(); }else{ - $p[] = RemoveEntityPacket::create($this->entityId); + $p[] = RemoveActorPacket::create($this->entityId); } if(!$this->invisible){