From c58a1bf9b76c7896642908521d90dacc9d027423 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Fri, 12 Jul 2019 18:33:02 +0100 Subject: [PATCH] Protocol changes for 1.12.0.28 --- src/pocketmine/Player.php | 14 +- src/pocketmine/entity/Entity.php | 158 ++++++------ src/pocketmine/entity/Human.php | 4 +- src/pocketmine/entity/Living.php | 8 +- src/pocketmine/entity/Squid.php | 4 +- src/pocketmine/entity/object/ItemEntity.php | 8 +- src/pocketmine/entity/object/Painting.php | 8 +- src/pocketmine/entity/projectile/Arrow.php | 8 +- src/pocketmine/level/Level.php | 4 +- src/pocketmine/level/format/Chunk.php | 5 +- .../level/format/io/ChunkRequestTask.php | 11 +- .../level/particle/FloatingTextParticle.php | 4 +- .../network/mcpe/NetworkBinaryStream.php | 72 +++++- .../network/mcpe/NetworkSession.php | 103 +++++--- .../mcpe/PlayerNetworkSessionAdapter.php | 16 +- ...tyEventPacket.php => ActorEventPacket.php} | 6 +- ...tityFallPacket.php => ActorFallPacket.php} | 6 +- ...tPacket.php => ActorPickRequestPacket.php} | 6 +- .../network/mcpe/protocol/AddActorPacket.php | 240 ++++++++++++++++++ .../network/mcpe/protocol/AddEntityPacket.php | 224 ++-------------- ...ntityPacket.php => AddItemActorPacket.php} | 6 +- .../mcpe/protocol/AddPaintingPacket.php | 19 +- .../AvailableActorIdentifiersPacket.php | 53 ++++ .../AvailableEntityIdentifiersPacket.php | 53 ---- ...ataPacket.php => BlockActorDataPacket.php} | 6 +- .../protocol/ClientCacheBlobStatusPacket.php | 95 +++++++ .../ClientCacheMissResponsePacket.php | 78 ++++++ .../mcpe/protocol/ClientCacheStatusPacket.php | 60 +++++ .../protocol/CommandBlockUpdatePacket.php | 8 + .../mcpe/protocol/CraftingDataPacket.php | 39 ++- .../mcpe/protocol/LevelChunkPacket.php | 145 +++++++++++ .../mcpe/protocol/LevelEventGenericPacket.php | 74 ++++++ ...Packet.php => MoveActorAbsolutePacket.php} | 6 +- ...ltaPacket.php => MoveActorDeltaPacket.php} | 6 +- .../network/mcpe/protocol/PacketPool.php | 41 +-- .../network/mcpe/protocol/ProtocolInfo.php | 53 ++-- .../mcpe/protocol/RemoveActorPacket.php | 48 ++++ .../mcpe/protocol/RemoveEntityPacket.php | 30 ++- .../protocol/ResourcePackDataInfoPacket.php | 8 + ...yDataPacket.php => SetActorDataPacket.php} | 6 +- ...yLinkPacket.php => SetActorLinkPacket.php} | 6 +- ...ionPacket.php => SetActorMotionPacket.php} | 6 +- .../network/mcpe/protocol/StartGamePacket.php | 70 +++-- ...ructureTemplateDataExportRequestPacket.php | 44 ++++ ...uctureTemplateDataExportResponsePacket.php | 44 ++++ ...tityPacket.php => TakeItemActorPacket.php} | 6 +- ...et.php => UpdateBlockPropertiesPacket.php} | 35 ++- .../protocol/VideoStreamConnectPacket.php | 8 + .../mcpe/protocol/types/ChunkCacheBlob.php | 56 ++++ .../protocol/types/RuntimeBlockMapping.php | 13 +- src/pocketmine/resources/vanilla | 2 +- src/pocketmine/tile/Spawnable.php | 6 +- 52 files changed, 1477 insertions(+), 562 deletions(-) rename src/pocketmine/network/mcpe/protocol/{EntityEventPacket.php => ActorEventPacket.php} (95%) rename src/pocketmine/network/mcpe/protocol/{EntityFallPacket.php => ActorFallPacket.php} (90%) rename src/pocketmine/network/mcpe/protocol/{EntityPickRequestPacket.php => ActorPickRequestPacket.php} (87%) create mode 100644 src/pocketmine/network/mcpe/protocol/AddActorPacket.php rename src/pocketmine/network/mcpe/protocol/{AddItemEntityPacket.php => AddItemActorPacket.php} (92%) create mode 100644 src/pocketmine/network/mcpe/protocol/AvailableActorIdentifiersPacket.php delete mode 100644 src/pocketmine/network/mcpe/protocol/AvailableEntityIdentifiersPacket.php rename src/pocketmine/network/mcpe/protocol/{BlockEntityDataPacket.php => BlockActorDataPacket.php} (88%) create mode 100644 src/pocketmine/network/mcpe/protocol/ClientCacheBlobStatusPacket.php create mode 100644 src/pocketmine/network/mcpe/protocol/ClientCacheMissResponsePacket.php create mode 100644 src/pocketmine/network/mcpe/protocol/ClientCacheStatusPacket.php create mode 100644 src/pocketmine/network/mcpe/protocol/LevelChunkPacket.php create mode 100644 src/pocketmine/network/mcpe/protocol/LevelEventGenericPacket.php rename src/pocketmine/network/mcpe/protocol/{MoveEntityAbsolutePacket.php => MoveActorAbsolutePacket.php} (91%) rename src/pocketmine/network/mcpe/protocol/{MoveEntityDeltaPacket.php => MoveActorDeltaPacket.php} (94%) create mode 100644 src/pocketmine/network/mcpe/protocol/RemoveActorPacket.php rename src/pocketmine/network/mcpe/protocol/{SetEntityDataPacket.php => SetActorDataPacket.php} (89%) rename src/pocketmine/network/mcpe/protocol/{SetEntityLinkPacket.php => SetActorLinkPacket.php} (88%) rename src/pocketmine/network/mcpe/protocol/{SetEntityMotionPacket.php => SetActorMotionPacket.php} (88%) create mode 100644 src/pocketmine/network/mcpe/protocol/StructureTemplateDataExportRequestPacket.php create mode 100644 src/pocketmine/network/mcpe/protocol/StructureTemplateDataExportResponsePacket.php rename src/pocketmine/network/mcpe/protocol/{TakeItemEntityPacket.php => TakeItemActorPacket.php} (88%) rename src/pocketmine/network/mcpe/protocol/{FullChunkDataPacket.php => UpdateBlockPropertiesPacket.php} (57%) create mode 100644 src/pocketmine/network/mcpe/protocol/types/ChunkCacheBlob.php diff --git a/src/pocketmine/Player.php b/src/pocketmine/Player.php index 493bfba82..574128367 100644 --- a/src/pocketmine/Player.php +++ b/src/pocketmine/Player.php @@ -102,17 +102,17 @@ use pocketmine\network\mcpe\PlayerNetworkSessionAdapter; use pocketmine\network\mcpe\protocol\AdventureSettingsPacket; use pocketmine\network\mcpe\protocol\AnimatePacket; use pocketmine\network\mcpe\protocol\AvailableCommandsPacket; -use pocketmine\network\mcpe\protocol\AvailableEntityIdentifiersPacket; +use pocketmine\network\mcpe\protocol\AvailableActorIdentifiersPacket; use pocketmine\network\mcpe\protocol\BatchPacket; use pocketmine\network\mcpe\protocol\BiomeDefinitionListPacket; -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\ChunkRadiusUpdatedPacket; use pocketmine\network\mcpe\protocol\ContainerClosePacket; use pocketmine\network\mcpe\protocol\DataPacket; use pocketmine\network\mcpe\protocol\DisconnectPacket; -use pocketmine\network\mcpe\protocol\EntityEventPacket; +use pocketmine\network\mcpe\protocol\ActorEventPacket; use pocketmine\network\mcpe\protocol\InteractPacket; use pocketmine\network\mcpe\protocol\InventoryTransactionPacket; use pocketmine\network\mcpe\protocol\ItemFrameDropItemPacket; @@ -2157,7 +2157,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{ $pk->worldName = $this->server->getMotd(); $this->dataPacket($pk); - $this->sendDataPacket(new AvailableEntityIdentifiersPacket()); + $this->sendDataPacket(new AvailableActorIdentifiersPacket()); $this->sendDataPacket(new BiomeDefinitionListPacket()); $this->level->sendTime($this); @@ -2279,14 +2279,14 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{ return true; } - public function handleEntityEvent(EntityEventPacket $packet) : bool{ + public function handleEntityEvent(ActorEventPacket $packet) : bool{ if(!$this->spawned or !$this->isAlive()){ return true; } $this->doCloseInventory(); switch($packet->event){ - case EntityEventPacket::EATING_ITEM: + case ActorEventPacket::EATING_ITEM: if($packet->data === 0){ return false; } @@ -2981,7 +2981,7 @@ class Player extends Human implements CommandSender, ChunkLoader, IPlayer{ return $handled; } - public function handleBlockEntityData(BlockEntityDataPacket $packet) : bool{ + public function handleBlockEntityData(BlockActorDataPacket $packet) : bool{ if(!$this->spawned or !$this->isAlive()){ return true; } diff --git a/src/pocketmine/entity/Entity.php b/src/pocketmine/entity/Entity.php index b7f9263a5..3941f5b95 100644 --- a/src/pocketmine/entity/Entity.php +++ b/src/pocketmine/entity/Entity.php @@ -62,12 +62,12 @@ 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\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\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\Player; use pocketmine\plugin\Plugin; use pocketmine\Server; @@ -154,70 +154,76 @@ abstract class Entity extends Location implements Metadatable, EntityIds{ public const DATA_LEAD_HOLDER_EID = 37; //long public const DATA_SCALE = 38; //float public const DATA_HAS_NPC_COMPONENT = 39; //byte (???) - public const DATA_SKIN_ID = 40; //string - public const DATA_NPC_SKIN_ID = 41; //string - public const DATA_URL_TAG = 42; //string - public const DATA_MAX_AIR = 43; //short - public const DATA_MARK_VARIANT = 44; //int - public const DATA_CONTAINER_TYPE = 45; //byte (ContainerComponent) - public const DATA_CONTAINER_BASE_SIZE = 46; //int (ContainerComponent) - public const DATA_CONTAINER_EXTRA_SLOTS_PER_STRENGTH = 47; //int (used for llamas, inventory size is baseSize + thisProp * strength) - public const DATA_BLOCK_TARGET = 48; //block coords (ender crystal) - public const DATA_WITHER_INVULNERABLE_TICKS = 49; //int - public const DATA_WITHER_TARGET_1 = 50; //long - public const DATA_WITHER_TARGET_2 = 51; //long - public const DATA_WITHER_TARGET_3 = 52; //long - /* 53 (short) */ - public const DATA_BOUNDING_BOX_WIDTH = 54; //float - public const DATA_BOUNDING_BOX_HEIGHT = 55; //float - public const DATA_FUSE_LENGTH = 56; //int - public const DATA_RIDER_SEAT_POSITION = 57; //vector3f - public const DATA_RIDER_ROTATION_LOCKED = 58; //byte - public const DATA_RIDER_MAX_ROTATION = 59; //float - public const DATA_RIDER_MIN_ROTATION = 60; //float - public const DATA_AREA_EFFECT_CLOUD_RADIUS = 61; //float - public const DATA_AREA_EFFECT_CLOUD_WAITING = 62; //int - public const DATA_AREA_EFFECT_CLOUD_PARTICLE_ID = 63; //int - /* 64 (int) shulker-related */ - public const DATA_SHULKER_ATTACH_FACE = 65; //byte - /* 66 (short) shulker-related */ - public const DATA_SHULKER_ATTACH_POS = 67; //block coords - public const DATA_TRADING_PLAYER_EID = 68; //long + public const DATA_NPC_SKIN_INDEX = 40; //string + public const DATA_NPC_ACTIONS = 41; //string (maybe JSON blob?) + public const DATA_MAX_AIR = 42; //short + public const DATA_MARK_VARIANT = 43; //int + public const DATA_CONTAINER_TYPE = 44; //byte (ContainerComponent) + public const DATA_CONTAINER_BASE_SIZE = 45; //int (ContainerComponent) + public const DATA_CONTAINER_EXTRA_SLOTS_PER_STRENGTH = 46; //int (used for llamas, inventory size is baseSize + thisProp * strength) + public const DATA_BLOCK_TARGET = 47; //block coords (ender crystal) + public const DATA_WITHER_INVULNERABLE_TICKS = 48; //int + public const DATA_WITHER_TARGET_1 = 49; //long + public const DATA_WITHER_TARGET_2 = 50; //long + public const DATA_WITHER_TARGET_3 = 51; //long + /* 52 (short) */ + public const DATA_BOUNDING_BOX_WIDTH = 53; //float + public const DATA_BOUNDING_BOX_HEIGHT = 54; //float + public const DATA_FUSE_LENGTH = 55; //int + public const DATA_RIDER_SEAT_POSITION = 56; //vector3f + public const DATA_RIDER_ROTATION_LOCKED = 57; //byte + public const DATA_RIDER_MAX_ROTATION = 58; //float + public const DATA_RIDER_MIN_ROTATION = 59; //float + public const DATA_AREA_EFFECT_CLOUD_RADIUS = 60; //float + public const DATA_AREA_EFFECT_CLOUD_WAITING = 61; //int + public const DATA_AREA_EFFECT_CLOUD_PARTICLE_ID = 62; //int + /* 63 (int) shulker-related */ + public const DATA_SHULKER_ATTACH_FACE = 64; //byte + /* 65 (short) shulker-related */ + public const DATA_SHULKER_ATTACH_POS = 66; //block coords + public const DATA_TRADING_PLAYER_EID = 67; //long - /* 70 (byte) command-block */ - public const DATA_COMMAND_BLOCK_COMMAND = 71; //string - public const DATA_COMMAND_BLOCK_LAST_OUTPUT = 72; //string - public const DATA_COMMAND_BLOCK_TRACK_OUTPUT = 73; //byte - public const DATA_CONTROLLING_RIDER_SEAT_NUMBER = 74; //byte - public const DATA_STRENGTH = 75; //int - public const DATA_MAX_STRENGTH = 76; //int - /* 77 (int) */ - public const DATA_LIMITED_LIFE = 78; - public const DATA_ARMOR_STAND_POSE_INDEX = 79; //int - public const DATA_ENDER_CRYSTAL_TIME_OFFSET = 80; //int - public const DATA_ALWAYS_SHOW_NAMETAG = 81; //byte: -1 = default, 0 = only when looked at, 1 = always - public const DATA_COLOR_2 = 82; //byte - /* 83 (unknown) */ - public const DATA_SCORE_TAG = 84; //string - public const DATA_BALLOON_ATTACHED_ENTITY = 85; //int64, entity unique ID of owner - public const DATA_PUFFERFISH_SIZE = 86; //byte - public const DATA_BOAT_BUBBLE_TIME = 87; //int (time in bubble column) - public const DATA_PLAYER_AGENT_EID = 88; //long - /* 89 (float) related to panda sitting - * 90 (float) related to panda sitting */ - public const DATA_EAT_COUNTER = 91; //int (used by pandas) - public const DATA_FLAGS2 = 92; //long (extended data flags) - /* 93 (float) related to panda lying down - * 94 (float) related to panda lying down */ - public const DATA_AREA_EFFECT_CLOUD_DURATION = 95; //int - public const DATA_AREA_EFFECT_CLOUD_SPAWN_TIME = 96; //int - public const DATA_AREA_EFFECT_CLOUD_RADIUS_PER_TICK = 97; //float, usually negative - public const DATA_AREA_EFFECT_CLOUD_RADIUS_CHANGE_ON_PICKUP = 98; //float - public const DATA_AREA_EFFECT_CLOUD_PICKUP_COUNT = 99; //int - public const DATA_INTERACTIVE_TAG = 100; //string (button text) - public const DATA_TRADE_TIER = 101; //int - public const DATA_MAX_TRADE_TIER = 102; //int - public const DATA_TRADE_XP = 103; //int + /* 69 (byte) command-block */ + public const DATA_COMMAND_BLOCK_COMMAND = 70; //string + public const DATA_COMMAND_BLOCK_LAST_OUTPUT = 71; //string + public const DATA_COMMAND_BLOCK_TRACK_OUTPUT = 72; //byte + public const DATA_CONTROLLING_RIDER_SEAT_NUMBER = 73; //byte + public const DATA_STRENGTH = 74; //int + public const DATA_MAX_STRENGTH = 75; //int + /* 76 (int) */ + public const DATA_LIMITED_LIFE = 77; + public const DATA_ARMOR_STAND_POSE_INDEX = 78; //int + public const DATA_ENDER_CRYSTAL_TIME_OFFSET = 79; //int + public const DATA_ALWAYS_SHOW_NAMETAG = 80; //byte: -1 = default, 0 = only when looked at, 1 = always + public const DATA_COLOR_2 = 81; //byte + /* 82 (unknown) */ + public const DATA_SCORE_TAG = 83; //string + public const DATA_BALLOON_ATTACHED_ENTITY = 84; //int64, entity unique ID of owner + public const DATA_PUFFERFISH_SIZE = 85; //byte + public const DATA_BOAT_BUBBLE_TIME = 86; //int (time in bubble column) + public const DATA_PLAYER_AGENT_EID = 87; //long + /* 88 (float) related to panda sitting + * 89 (float) related to panda sitting */ + public const DATA_EAT_COUNTER = 90; //int (used by pandas) + public const DATA_FLAGS2 = 91; //long (extended data flags) + /* 92 (float) related to panda lying down + * 93 (float) related to panda lying down */ + public const DATA_AREA_EFFECT_CLOUD_DURATION = 94; //int + public const DATA_AREA_EFFECT_CLOUD_SPAWN_TIME = 95; //int + public const DATA_AREA_EFFECT_CLOUD_RADIUS_PER_TICK = 96; //float, usually negative + public const DATA_AREA_EFFECT_CLOUD_RADIUS_CHANGE_ON_PICKUP = 97; //float + public const DATA_AREA_EFFECT_CLOUD_PICKUP_COUNT = 98; //int + public const DATA_INTERACTIVE_TAG = 99; //string (button text) + public const DATA_TRADE_TIER = 100; //int + public const DATA_MAX_TRADE_TIER = 101; //int + public const DATA_TRADE_XP = 102; //int + public const DATA_SKIN_ID = 103; //int ??? + /* 104 (int) related to wither */ + public const DATA_COMMAND_BLOCK_TICK_DELAY = 105; //int + public const DATA_COMMAND_BLOCK_EXECUTE_ON_FIRST_TICK = 106; //byte + public const DATA_AMBIENT_SOUND_INTERVAL_MIN = 107; //float + public const DATA_AMBIENT_SOUND_INTERVAL_RANGE = 108; //float + public const DATA_AMBIENT_SOUND_EVENT = 109; //string public const DATA_FLAG_ONFIRE = 0; public const DATA_FLAG_SNEAKING = 1; @@ -1235,7 +1241,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{ } protected function broadcastMovement(bool $teleport = false) : void{ - $pk = new MoveEntityAbsolutePacket(); + $pk = new MoveActorAbsolutePacket(); $pk->entityRuntimeId = $this->id; $pk->position = $this->getOffsetPosition($this); @@ -1247,14 +1253,14 @@ abstract class Entity extends Location implements Metadatable, EntityIds{ $pk->zRot = $this->yaw; if($teleport){ - $pk->flags |= MoveEntityAbsolutePacket::FLAG_TELEPORT; + $pk->flags |= MoveActorAbsolutePacket::FLAG_TELEPORT; } $this->level->broadcastPacketToViewers($this, $pk); } protected function broadcastMotion() : void{ - $pk = new SetEntityMotionPacket(); + $pk = new SetActorMotionPacket(); $pk->entityRuntimeId = $this->id; $pk->motion = $this->getMotion(); @@ -2021,7 +2027,7 @@ abstract class Entity extends Location implements Metadatable, 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(); @@ -2071,7 +2077,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{ public function despawnFrom(Player $player, bool $send = true) : void{ if(isset($this->hasSpawned[$player->getLoaderId()])){ if($send){ - $pk = new RemoveEntityPacket(); + $pk = new RemoveActorPacket(); $pk->entityUniqueId = $this->id; $player->dataPacket($pk); } @@ -2193,7 +2199,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{ $player = [$player]; } - $pk = new SetEntityDataPacket(); + $pk = new SetActorDataPacket(); $pk->entityRuntimeId = $this->getId(); $pk->metadata = $data ?? $this->propertyManager->getAll(); @@ -2210,7 +2216,7 @@ abstract class Entity extends Location implements Metadatable, EntityIds{ } public function broadcastEntityEvent(int $eventId, ?int $eventData = null, ?array $players = null) : void{ - $pk = new EntityEventPacket(); + $pk = new ActorEventPacket(); $pk->entityRuntimeId = $this->id; $pk->event = $eventId; $pk->data = $eventData ?? 0; diff --git a/src/pocketmine/entity/Human.php b/src/pocketmine/entity/Human.php index 705246a02..0bece64e6 100644 --- a/src/pocketmine/entity/Human.php +++ b/src/pocketmine/entity/Human.php @@ -47,7 +47,7 @@ use pocketmine\nbt\tag\IntTag; use pocketmine\nbt\tag\ListTag; use pocketmine\nbt\tag\StringTag; use pocketmine\network\mcpe\protocol\AddPlayerPacket; -use pocketmine\network\mcpe\protocol\EntityEventPacket; +use pocketmine\network\mcpe\protocol\ActorEventPacket; use pocketmine\network\mcpe\protocol\LevelEventPacket; use pocketmine\network\mcpe\protocol\LevelSoundEventPacket; use pocketmine\network\mcpe\protocol\PlayerListPacket; @@ -754,7 +754,7 @@ class Human extends Creature implements ProjectileSource, InventoryHolder{ $this->addEffect(new EffectInstance(Effect::getEffect(Effect::FIRE_RESISTANCE), 40 * 20, 1)); $this->addEffect(new EffectInstance(Effect::getEffect(Effect::ABSORPTION), 5 * 20, 1)); - $this->broadcastEntityEvent(EntityEventPacket::CONSUME_TOTEM); + $this->broadcastEntityEvent(ActorEventPacket::CONSUME_TOTEM); $this->level->broadcastLevelEvent($this->add(0, $this->eyeHeight, 0), LevelEventPacket::EVENT_SOUND_TOTEM); $hand = $this->inventory->getItemInHand(); diff --git a/src/pocketmine/entity/Living.php b/src/pocketmine/entity/Living.php index 3dd029596..504304e97 100644 --- a/src/pocketmine/entity/Living.php +++ b/src/pocketmine/entity/Living.php @@ -44,7 +44,7 @@ use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\FloatTag; use pocketmine\nbt\tag\IntTag; use pocketmine\nbt\tag\ListTag; -use pocketmine\network\mcpe\protocol\EntityEventPacket; +use pocketmine\network\mcpe\protocol\ActorEventPacket; use pocketmine\network\mcpe\protocol\LevelSoundEventPacket; use pocketmine\network\mcpe\protocol\MobEffectPacket; use pocketmine\Player; @@ -143,7 +143,7 @@ abstract class Living extends Entity implements Damageable{ 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); } } @@ -606,7 +606,7 @@ abstract class Living extends Entity implements Damageable{ } protected function doHitAnimation() : void{ - $this->broadcastEntityEvent(EntityEventPacket::HURT_ANIMATION); + $this->broadcastEntityEvent(ActorEventPacket::HURT_ANIMATION); } public function knockBack(Entity $attacker, float $damage, float $x, float $z, float $base = 0.4) : void{ @@ -664,7 +664,7 @@ abstract class Living extends Entity implements Damageable{ } 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 7c8ce50e0..8592821af 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\Item; use pocketmine\item\ItemFactory; use pocketmine\math\Vector3; -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 edf6c3aac..71fd1a3c0 100644 --- a/src/pocketmine/entity/object/ItemEntity.php +++ b/src/pocketmine/entity/object/ItemEntity.php @@ -28,8 +28,8 @@ use pocketmine\event\entity\ItemDespawnEvent; use pocketmine\event\entity\ItemSpawnEvent; use pocketmine\event\inventory\InventoryPickupItemEvent; use pocketmine\item\Item; -use pocketmine\network\mcpe\protocol\AddItemEntityPacket; -use pocketmine\network\mcpe\protocol\TakeItemEntityPacket; +use pocketmine\network\mcpe\protocol\AddItemActorPacket; +use pocketmine\network\mcpe\protocol\TakeItemActorPacket; use pocketmine\Player; use function get_class; @@ -192,7 +192,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(); @@ -229,7 +229,7 @@ class ItemEntity extends Entity{ break; } - $pk = new TakeItemEntityPacket(); + $pk = new TakeItemActorPacket(); $pk->eid = $player->getId(); $pk->target = $this->getId(); $this->server->broadcastPacket($this->getViewers(), $pk); diff --git a/src/pocketmine/entity/object/Painting.php b/src/pocketmine/entity/object/Painting.php index 93b3f041f..70e47307f 100644 --- a/src/pocketmine/entity/object/Painting.php +++ b/src/pocketmine/entity/object/Painting.php @@ -152,9 +152,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 0fa86b323..4ae8f6a4c 100644 --- a/src/pocketmine/entity/projectile/Arrow.php +++ b/src/pocketmine/entity/projectile/Arrow.php @@ -32,9 +32,9 @@ use pocketmine\item\ItemFactory; use pocketmine\level\Level; use pocketmine\math\RayTraceResult; use pocketmine\nbt\tag\CompoundTag; -use pocketmine\network\mcpe\protocol\EntityEventPacket; +use pocketmine\network\mcpe\protocol\ActorEventPacket; use pocketmine\network\mcpe\protocol\LevelSoundEventPacket; -use pocketmine\network\mcpe\protocol\TakeItemEntityPacket; +use pocketmine\network\mcpe\protocol\TakeItemActorPacket; use pocketmine\Player; use function mt_rand; use function sqrt; @@ -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; } - $pk = new TakeItemEntityPacket(); + $pk = new TakeItemActorPacket(); $pk->eid = $player->getId(); $pk->target = $this->getId(); $this->server->broadcastPacket($this->getViewers(), $pk); diff --git a/src/pocketmine/level/Level.php b/src/pocketmine/level/Level.php index b42ae887e..754312852 100644 --- a/src/pocketmine/level/Level.php +++ b/src/pocketmine/level/Level.php @@ -72,7 +72,7 @@ use pocketmine\metadata\Metadatable; use pocketmine\metadata\MetadataValue; use pocketmine\nbt\tag\ListTag; use pocketmine\nbt\tag\StringTag; -use pocketmine\network\mcpe\protocol\AddEntityPacket; +use pocketmine\network\mcpe\protocol\AddActorPacket; use pocketmine\network\mcpe\protocol\BatchPacket; use pocketmine\network\mcpe\protocol\DataPacket; use pocketmine\network\mcpe\protocol\LevelEventPacket; @@ -564,7 +564,7 @@ class Level implements ChunkManager, Metadatable{ $pk = new LevelSoundEventPacket(); $pk->sound = $soundId; $pk->extraData = $extraData; - $pk->entityType = AddEntityPacket::LEGACY_ID_MAP_BC[$entityTypeId] ?? ":"; + $pk->entityType = AddActorPacket::LEGACY_ID_MAP_BC[$entityTypeId] ?? ":"; $pk->isBabyMob = $isBabyMob; $pk->disableRelativeVolume = $disableRelativeVolume; $pk->position = $pos->asVector3(); diff --git a/src/pocketmine/level/format/Chunk.php b/src/pocketmine/level/format/Chunk.php index 8cecf5321..deadc83df 100644 --- a/src/pocketmine/level/format/Chunk.php +++ b/src/pocketmine/level/format/Chunk.php @@ -869,13 +869,10 @@ class Chunk{ public function networkSerialize() : string{ $result = ""; $subChunkCount = $this->getSubChunkSendCount(); - $result .= chr($subChunkCount); for($y = 0; $y < $subChunkCount; ++$y){ $result .= $this->subChunks[$y]->networkSerialize(); } - $result .= pack("v*", ...$this->heightMap) - . $this->biomeIds - . chr(0); //border block array count + $result .= $this->biomeIds . chr(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. foreach($this->tiles as $tile){ diff --git a/src/pocketmine/level/format/io/ChunkRequestTask.php b/src/pocketmine/level/format/io/ChunkRequestTask.php index 52f5419a8..07bf31eb0 100644 --- a/src/pocketmine/level/format/io/ChunkRequestTask.php +++ b/src/pocketmine/level/format/io/ChunkRequestTask.php @@ -26,7 +26,7 @@ namespace pocketmine\level\format\io; use pocketmine\level\format\Chunk; use pocketmine\level\Level; use pocketmine\network\mcpe\protocol\BatchPacket; -use pocketmine\network\mcpe\protocol\FullChunkDataPacket; +use pocketmine\network\mcpe\protocol\LevelChunkPacket; use pocketmine\scheduler\AsyncTask; use pocketmine\Server; use function assert; @@ -42,6 +42,9 @@ class ChunkRequestTask extends AsyncTask{ protected $compressionLevel; + /** @var int */ + private $subChunkCount; + public function __construct(Level $level, int $chunkX, int $chunkZ, Chunk $chunk){ $this->levelId = $level->getId(); $this->compressionLevel = $level->getServer()->networkCompressionLevel; @@ -49,13 +52,11 @@ class ChunkRequestTask extends AsyncTask{ $this->chunk = $chunk->networkSerialize(); $this->chunkX = $chunkX; $this->chunkZ = $chunkZ; + $this->subChunkCount = $chunk->getSubChunkSendCount(); } public function onRun(){ - $pk = new FullChunkDataPacket(); - $pk->chunkX = $this->chunkX; - $pk->chunkZ = $this->chunkZ; - $pk->data = $this->chunk; + $pk = LevelChunkPacket::withoutCache($this->chunkX, $this->chunkZ, $this->subChunkCount, $this->chunk); $batch = new BatchPacket(); $batch->addPacket($pk); diff --git a/src/pocketmine/level/particle/FloatingTextParticle.php b/src/pocketmine/level/particle/FloatingTextParticle.php index 746827063..d12282874 100644 --- a/src/pocketmine/level/particle/FloatingTextParticle.php +++ b/src/pocketmine/level/particle/FloatingTextParticle.php @@ -30,7 +30,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\PlayerListEntry; use pocketmine\utils\UUID; use function str_repeat; @@ -84,7 +84,7 @@ class FloatingTextParticle extends Particle{ if($this->entityId === null){ $this->entityId = Entity::$entityCount++; }else{ - $pk0 = new RemoveEntityPacket(); + $pk0 = new RemoveActorPacket(); $pk0->entityUniqueId = $this->entityId; $p[] = $pk0; diff --git a/src/pocketmine/network/mcpe/NetworkBinaryStream.php b/src/pocketmine/network/mcpe/NetworkBinaryStream.php index 5dc1fb885..9d4edd400 100644 --- a/src/pocketmine/network/mcpe/NetworkBinaryStream.php +++ b/src/pocketmine/network/mcpe/NetworkBinaryStream.php @@ -27,21 +27,27 @@ namespace pocketmine\network\mcpe; use pocketmine\entity\Attribute; use pocketmine\entity\Entity; +use pocketmine\item\Durable; use pocketmine\item\Item; use pocketmine\item\ItemFactory; use pocketmine\item\ItemIds; use pocketmine\math\Vector3; use pocketmine\nbt\NetworkLittleEndianNBTStream; use pocketmine\nbt\tag\CompoundTag; +use pocketmine\nbt\tag\IntTag; use pocketmine\network\mcpe\protocol\types\CommandOriginData; use pocketmine\network\mcpe\protocol\types\EntityLink; use pocketmine\utils\BinaryStream; use pocketmine\utils\UUID; use function count; use function strlen; +use function var_dump; class NetworkBinaryStream extends BinaryStream{ + private const DAMAGE_TAG = "Damage"; //TAG_Int + private const DAMAGE_TAG_CONFLICT_RESOLUTION = "___Damage_ProtocolCollisionResolution___"; + public function getString() : string{ return $this->get($this->getUnsignedVarInt()); } @@ -76,15 +82,12 @@ class NetworkBinaryStream extends BinaryStream{ $auxValue = $this->getVarInt(); $data = $auxValue >> 8; - if($data === 0x7fff){ - $data = -1; - } $cnt = $auxValue & 0xff; $nbtLen = $this->getLShort(); - /** @var CompoundTag|string $nbt */ - $nbt = ""; + /** @var CompoundTag|null $nbt */ + $nbt = null; if($nbtLen === 0xffff){ $c = $this->getByte(); if($c !== 1){ @@ -108,7 +111,22 @@ class NetworkBinaryStream extends BinaryStream{ if($id === ItemIds::SHIELD){ $this->getVarLong(); //"blocking tick" (ffs mojang) } - + if($nbt !== null){ + if($nbt->hasTag(self::DAMAGE_TAG, IntTag::class)){ + $data = $nbt->getInt(self::DAMAGE_TAG); + $nbt->removeTag(self::DAMAGE_TAG); + if($nbt->count() === 0){ + $nbt = null; + goto end; + } + } + if(($conflicted = $nbt->getTag(self::DAMAGE_TAG_CONFLICT_RESOLUTION)) !== null){ + $nbt->removeTag(self::DAMAGE_TAG_CONFLICT_RESOLUTION); + $conflicted->setName(self::DAMAGE_TAG); + $nbt->setTag($conflicted); + } + } + end: return ItemFactory::get($id, $data, $cnt, $nbt); } @@ -124,10 +142,27 @@ class NetworkBinaryStream extends BinaryStream{ $auxValue = (($item->getDamage() & 0x7fff) << 8) | $item->getCount(); $this->putVarInt($auxValue); + $nbt = null; if($item->hasCompoundTag()){ + $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); + $existing->setName(self::DAMAGE_TAG_CONFLICT_RESOLUTION); + $nbt->setTag($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 NetworkLittleEndianNBTStream())->write($item->getNamedTag())); + $this->put((new NetworkLittleEndianNBTStream())->write($nbt)); }else{ $this->putLShort(0); } @@ -140,6 +175,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->getDamage() & 0x7fff); + $this->putVarInt($item->getCount()); + } + } + /** * Decodes entity metadata from the stream. * diff --git a/src/pocketmine/network/mcpe/NetworkSession.php b/src/pocketmine/network/mcpe/NetworkSession.php index 4054473bd..4de360f3a 100644 --- a/src/pocketmine/network/mcpe/NetworkSession.php +++ b/src/pocketmine/network/mcpe/NetworkSession.php @@ -23,18 +23,22 @@ declare(strict_types=1); namespace pocketmine\network\mcpe; +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; @@ -54,12 +61,8 @@ use pocketmine\network\mcpe\protocol\CraftingDataPacket; use pocketmine\network\mcpe\protocol\CraftingEventPacket; use pocketmine\network\mcpe\protocol\DataPacket; 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; @@ -70,6 +73,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; @@ -82,8 +87,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; @@ -98,6 +103,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; @@ -113,13 +119,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; @@ -138,12 +144,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; @@ -202,23 +211,23 @@ abstract class NetworkSession{ 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; } @@ -254,7 +263,7 @@ abstract class NetworkSession{ return false; } - public function handleEntityEvent(EntityEventPacket $packet) : bool{ + public function handleActorEvent(ActorEventPacket $packet) : bool{ return false; } @@ -286,7 +295,7 @@ abstract class NetworkSession{ return false; } - public function handleEntityPickRequest(EntityPickRequestPacket $packet) : bool{ + public function handleActorPickRequest(ActorPickRequestPacket $packet) : bool{ return false; } @@ -294,7 +303,7 @@ abstract class NetworkSession{ return false; } - public function handleEntityFall(EntityFallPacket $packet) : bool{ + public function handleActorFall(ActorFallPacket $packet) : bool{ return false; } @@ -302,15 +311,15 @@ abstract class NetworkSession{ 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; } @@ -370,7 +379,7 @@ abstract class NetworkSession{ return false; } - public function handleBlockEntityData(BlockEntityDataPacket $packet) : bool{ + public function handleBlockActorData(BlockActorDataPacket $packet) : bool{ return false; } @@ -378,7 +387,7 @@ abstract class NetworkSession{ return false; } - public function handleFullChunkData(FullChunkDataPacket $packet) : bool{ + public function handleLevelChunk(LevelChunkPacket $packet) : bool{ return false; } @@ -590,7 +599,7 @@ abstract class NetworkSession{ return false; } - public function handleMoveEntityDelta(MoveEntityDeltaPacket $packet) : bool{ + public function handleMoveActorDelta(MoveActorDeltaPacket $packet) : bool{ return false; } @@ -618,7 +627,7 @@ abstract class NetworkSession{ return false; } - public function handleAvailableEntityIdentifiers(AvailableEntityIdentifiersPacket $packet) : bool{ + public function handleAvailableActorIdentifiers(AvailableActorIdentifiersPacket $packet) : bool{ return false; } @@ -638,6 +647,10 @@ abstract class NetworkSession{ return false; } + public function handleLevelEventGeneric(LevelEventGenericPacket $packet) : bool{ + return false; + } + public function handleLecternUpdate(LecternUpdatePacket $packet) : bool{ return false; } @@ -646,11 +659,43 @@ abstract class NetworkSession{ 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/PlayerNetworkSessionAdapter.php b/src/pocketmine/network/mcpe/PlayerNetworkSessionAdapter.php index 53afe17be..44ca2ef60 100644 --- a/src/pocketmine/network/mcpe/PlayerNetworkSessionAdapter.php +++ b/src/pocketmine/network/mcpe/PlayerNetworkSessionAdapter.php @@ -27,7 +27,7 @@ namespace pocketmine\network\mcpe; use pocketmine\event\server\DataPacketReceiveEvent; 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; @@ -37,9 +37,9 @@ use pocketmine\network\mcpe\protocol\CommandRequestPacket; use pocketmine\network\mcpe\protocol\ContainerClosePacket; use pocketmine\network\mcpe\protocol\CraftingEventPacket; use pocketmine\network\mcpe\protocol\DataPacket; -use pocketmine\network\mcpe\protocol\EntityEventPacket; -use pocketmine\network\mcpe\protocol\EntityFallPacket; -use pocketmine\network\mcpe\protocol\EntityPickRequestPacket; +use pocketmine\network\mcpe\protocol\ActorEventPacket; +use pocketmine\network\mcpe\protocol\ActorFallPacket; +use pocketmine\network\mcpe\protocol\ActorPickRequestPacket; use pocketmine\network\mcpe\protocol\InteractPacket; use pocketmine\network\mcpe\protocol\InventoryTransactionPacket; use pocketmine\network\mcpe\protocol\ItemFrameDropItemPacket; @@ -142,7 +142,7 @@ class PlayerNetworkSessionAdapter extends NetworkSession{ return true; //useless leftover from 1.8 } - public function handleEntityEvent(EntityEventPacket $packet) : bool{ + public function handleActorEvent(ActorEventPacket $packet) : bool{ return $this->player->handleEntityEvent($packet); } @@ -166,7 +166,7 @@ class PlayerNetworkSessionAdapter extends NetworkSession{ return $this->player->handleBlockPickRequest($packet); } - public function handleEntityPickRequest(EntityPickRequestPacket $packet) : bool{ + public function handleActorPickRequest(ActorPickRequestPacket $packet) : bool{ return false; //TODO } @@ -174,7 +174,7 @@ class PlayerNetworkSessionAdapter extends NetworkSession{ return $this->player->handlePlayerAction($packet); } - public function handleEntityFall(EntityFallPacket $packet) : bool{ + public function handleActorFall(ActorFallPacket $packet) : bool{ return true; //Not used } @@ -198,7 +198,7 @@ class PlayerNetworkSessionAdapter extends NetworkSession{ return $this->player->handleAdventureSettings($packet); } - public function handleBlockEntityData(BlockEntityDataPacket $packet) : bool{ + public function handleBlockActorData(BlockActorDataPacket $packet) : bool{ return $this->player->handleBlockEntityData($packet); } diff --git a/src/pocketmine/network/mcpe/protocol/EntityEventPacket.php b/src/pocketmine/network/mcpe/protocol/ActorEventPacket.php similarity index 95% rename from src/pocketmine/network/mcpe/protocol/EntityEventPacket.php rename to src/pocketmine/network/mcpe/protocol/ActorEventPacket.php index 19e5fbd19..531309efa 100644 --- a/src/pocketmine/network/mcpe/protocol/EntityEventPacket.php +++ b/src/pocketmine/network/mcpe/protocol/ActorEventPacket.php @@ -28,8 +28,8 @@ namespace pocketmine\network\mcpe\protocol; use pocketmine\network\mcpe\NetworkSession; -class EntityEventPacket extends DataPacket{ - public const NETWORK_ID = ProtocolInfo::ENTITY_EVENT_PACKET; +class ActorEventPacket extends DataPacket{ + public const NETWORK_ID = ProtocolInfo::ACTOR_EVENT_PACKET; public const HURT_ANIMATION = 2; public const DEATH_ANIMATION = 3; @@ -103,6 +103,6 @@ class EntityEventPacket extends DataPacket{ } public function handle(NetworkSession $session) : bool{ - return $session->handleEntityEvent($this); + return $session->handleActorEvent($this); } } diff --git a/src/pocketmine/network/mcpe/protocol/EntityFallPacket.php b/src/pocketmine/network/mcpe/protocol/ActorFallPacket.php similarity index 90% rename from src/pocketmine/network/mcpe/protocol/EntityFallPacket.php rename to src/pocketmine/network/mcpe/protocol/ActorFallPacket.php index 4c3c5cd6c..76f8dca7a 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\NetworkSession; -class EntityFallPacket extends DataPacket{ - public const NETWORK_ID = ProtocolInfo::ENTITY_FALL_PACKET; +class ActorFallPacket extends DataPacket{ + public const NETWORK_ID = ProtocolInfo::ACTOR_FALL_PACKET; /** @var int */ public $entityRuntimeId; @@ -51,6 +51,6 @@ class EntityFallPacket extends DataPacket{ } public function handle(NetworkSession $session) : bool{ - return $session->handleEntityFall($this); + return $session->handleActorFall($this); } } diff --git a/src/pocketmine/network/mcpe/protocol/EntityPickRequestPacket.php b/src/pocketmine/network/mcpe/protocol/ActorPickRequestPacket.php similarity index 87% rename from src/pocketmine/network/mcpe/protocol/EntityPickRequestPacket.php rename to src/pocketmine/network/mcpe/protocol/ActorPickRequestPacket.php index 96b6c7b2e..ed9a913c0 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\NetworkSession; -class EntityPickRequestPacket extends DataPacket{ - public const NETWORK_ID = ProtocolInfo::ENTITY_PICK_REQUEST_PACKET; +class ActorPickRequestPacket extends DataPacket{ + public const NETWORK_ID = ProtocolInfo::ACTOR_PICK_REQUEST_PACKET; /** @var int */ public $entityUniqueId; @@ -46,6 +46,6 @@ class EntityPickRequestPacket extends DataPacket{ } public function handle(NetworkSession $session) : bool{ - return $session->handleEntityPickRequest($this); + return $session->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..50aade6fa --- /dev/null +++ b/src/pocketmine/network/mcpe/protocol/AddActorPacket.php @@ -0,0 +1,240 @@ + + +use pocketmine\entity\Attribute; +use pocketmine\entity\EntityIds; +use pocketmine\math\Vector3; +use pocketmine\network\mcpe\NetworkSession; +use pocketmine\network\mcpe\protocol\types\EntityLink; +use function array_search; +use function count; + +class AddActorPacket extends DataPacket{ + public const NETWORK_ID = ProtocolInfo::ADD_ACTOR_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(){ + $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 \UnexpectedValueException("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){ + $name = $this->getString(); + $min = $this->getLFloat(); + $current = $this->getLFloat(); + $max = $this->getLFloat(); + $attr = Attribute::getAttributeByName($name); + + if($attr !== null){ + $attr->setMinValue($min); + $attr->setMaxValue($max); + $attr->setValue($current); + $this->attributes[] = $attr; + }else{ + throw new \UnexpectedValueException("Unknown attribute type \"$name\""); + } + } + + $this->metadata = $this->getEntityMetadata(); + $linkCount = $this->getUnsignedVarInt(); + for($i = 0; $i < $linkCount; ++$i){ + $this->links[] = $this->getEntityLink(); + } + } + + protected function encodePayload(){ + $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->getName()); + $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(NetworkSession $session) : bool{ + return $session->handleAddActor($this); + } +} diff --git a/src/pocketmine/network/mcpe/protocol/AddEntityPacket.php b/src/pocketmine/network/mcpe/protocol/AddEntityPacket.php index e725c845c..ba428cbcb 100644 --- a/src/pocketmine/network/mcpe/protocol/AddEntityPacket.php +++ b/src/pocketmine/network/mcpe/protocol/AddEntityPacket.php @@ -25,216 +25,36 @@ namespace pocketmine\network\mcpe\protocol; #include -use pocketmine\entity\Attribute; -use pocketmine\entity\EntityIds; -use pocketmine\math\Vector3; use pocketmine\network\mcpe\NetworkSession; -use pocketmine\network\mcpe\protocol\types\EntityLink; -use function array_search; -use function count; -class AddEntityPacket extends DataPacket{ +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 = []; - - protected function decodePayload(){ - $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 \UnexpectedValueException("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){ - $name = $this->getString(); - $min = $this->getLFloat(); - $current = $this->getLFloat(); - $max = $this->getLFloat(); - $attr = Attribute::getAttributeByName($name); - - if($attr !== null){ - $attr->setMinValue($min); - $attr->setMaxValue($max); - $attr->setValue($current); - $this->attributes[] = $attr; - }else{ - throw new \UnexpectedValueException("Unknown attribute type \"$name\""); - } - } - - $this->metadata = $this->getEntityMetadata(); - $linkCount = $this->getUnsignedVarInt(); - for($i = 0; $i < $linkCount; ++$i){ - $this->links[] = $this->getEntityLink(); - } + public function getUvarint1() : int{ + return $this->uvarint1; } - protected function encodePayload(){ - $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->getName()); - $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); - } + protected function decodePayload() : void{ + $this->uvarint1 = $this->getUnsignedVarInt(); } - public function handle(NetworkSession $session) : bool{ - return $session->handleAddEntity($this); + protected function encodePayload() : void{ + $this->putUnsignedVarInt($this->uvarint1); + } + + public function handle(NetworkSession $handler) : bool{ + return $handler->handleAddEntity($this); } } diff --git a/src/pocketmine/network/mcpe/protocol/AddItemEntityPacket.php b/src/pocketmine/network/mcpe/protocol/AddItemActorPacket.php similarity index 92% rename from src/pocketmine/network/mcpe/protocol/AddItemEntityPacket.php rename to src/pocketmine/network/mcpe/protocol/AddItemActorPacket.php index 9e2772e4e..13492dae4 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\NetworkSession; -class AddItemEntityPacket extends DataPacket{ - public const NETWORK_ID = ProtocolInfo::ADD_ITEM_ENTITY_PACKET; +class AddItemActorPacket extends DataPacket{ + public const NETWORK_ID = ProtocolInfo::ADD_ITEM_ACTOR_PACKET; /** @var int|null */ public $entityUniqueId = null; //TODO @@ -68,6 +68,6 @@ class AddItemEntityPacket extends DataPacket{ } public function handle(NetworkSession $session) : bool{ - return $session->handleAddItemEntity($this); + return $session->handleAddItemActor($this); } } diff --git a/src/pocketmine/network/mcpe/protocol/AddPaintingPacket.php b/src/pocketmine/network/mcpe/protocol/AddPaintingPacket.php index dfb8878ce..4b6491adf 100644 --- a/src/pocketmine/network/mcpe/protocol/AddPaintingPacket.php +++ b/src/pocketmine/network/mcpe/protocol/AddPaintingPacket.php @@ -26,30 +26,27 @@ namespace pocketmine\network\mcpe\protocol; #include +use pocketmine\math\Vector3; use pocketmine\network\mcpe\NetworkSession; class AddPaintingPacket extends DataPacket{ public const NETWORK_ID = ProtocolInfo::ADD_PAINTING_PACKET; - /** @var string */ - public $title; - /** @var int */ - public $entityRuntimeId; - /** @var int */ - public $x; /** @var int|null */ public $entityUniqueId = null; /** @var int */ - public $y; - /** @var int */ - public $z; + public $entityRuntimeId; + /** @var Vector3 */ + public $position; /** @var int */ public $direction; + /** @var string */ + public $title; protected function decodePayload(){ $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 +54,7 @@ class AddPaintingPacket extends DataPacket{ protected function encodePayload(){ $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..c70ece1b0 --- /dev/null +++ b/src/pocketmine/network/mcpe/protocol/AvailableActorIdentifiersPacket.php @@ -0,0 +1,53 @@ + + +use pocketmine\network\mcpe\NetworkSession; +use function base64_decode; + +class AvailableActorIdentifiersPacket extends DataPacket{ + 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(){ + $this->namedtag = $this->getRemaining(); + } + + protected function encodePayload(){ + $this->put($this->namedtag ?? base64_decode(self::HARDCODED_NBT_BLOB)); + } + + public function handle(NetworkSession $session) : bool{ + return $session->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 bc8b7b439..000000000 --- a/src/pocketmine/network/mcpe/protocol/AvailableEntityIdentifiersPacket.php +++ /dev/null @@ -1,53 +0,0 @@ - - -use pocketmine\network\mcpe\NetworkSession; -use function base64_decode; - -class AvailableEntityIdentifiersPacket extends DataPacket{ - 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(){ - $this->namedtag = $this->getRemaining(); - } - - protected function encodePayload(){ - $this->put($this->namedtag ?? base64_decode(self::HARDCODED_NBT_BLOB)); - } - - public function handle(NetworkSession $session) : bool{ - return $session->handleAvailableEntityIdentifiers($this); - } -} diff --git a/src/pocketmine/network/mcpe/protocol/BlockEntityDataPacket.php b/src/pocketmine/network/mcpe/protocol/BlockActorDataPacket.php similarity index 88% rename from src/pocketmine/network/mcpe/protocol/BlockEntityDataPacket.php rename to src/pocketmine/network/mcpe/protocol/BlockActorDataPacket.php index e936f01e5..01bb20f1e 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\NetworkSession; -class BlockEntityDataPacket extends DataPacket{ - public const NETWORK_ID = ProtocolInfo::BLOCK_ENTITY_DATA_PACKET; +class BlockActorDataPacket extends DataPacket{ + public const NETWORK_ID = ProtocolInfo::BLOCK_ACTOR_DATA_PACKET; /** @var int */ public $x; @@ -51,6 +51,6 @@ class BlockEntityDataPacket extends DataPacket{ } public function handle(NetworkSession $session) : bool{ - return $session->handleBlockEntityData($this); + return $session->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..81ca48163 --- /dev/null +++ b/src/pocketmine/network/mcpe/protocol/ClientCacheBlobStatusPacket.php @@ -0,0 +1,95 @@ + + +use pocketmine\network\mcpe\NetworkSession; +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(NetworkSession $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..ca1bc7f53 --- /dev/null +++ b/src/pocketmine/network/mcpe/protocol/ClientCacheMissResponsePacket.php @@ -0,0 +1,78 @@ + + +use function count; +use pocketmine\network\mcpe\NetworkSession; +use pocketmine\network\mcpe\protocol\types\ChunkCacheBlob; + +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(NetworkSession $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..a7eb0f824 --- /dev/null +++ b/src/pocketmine/network/mcpe/protocol/ClientCacheStatusPacket.php @@ -0,0 +1,60 @@ + + +use pocketmine\network\mcpe\NetworkSession; + +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(NetworkSession $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 be810fbc1..e88f80c9a 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{ public $name; /** @var bool */ public $shouldTrackOutput; + /** @var int */ + public $tickDelay; + /** @var bool */ + public $executeOnFirstTick; protected function decodePayload(){ $this->isBlock = $this->getBool(); @@ -78,6 +82,8 @@ class CommandBlockUpdatePacket extends DataPacket{ $this->name = $this->getString(); $this->shouldTrackOutput = $this->getBool(); + $this->tickDelay = $this->getLInt(); + $this->executeOnFirstTick = $this->getBool(); } protected function encodePayload(){ @@ -97,6 +103,8 @@ class CommandBlockUpdatePacket extends DataPacket{ $this->putString($this->name); $this->putBool($this->shouldTrackOutput); + $this->putLInt($this->tickDelay); + $this->putBool($this->executeOnFirstTick); } public function handle(NetworkSession $session) : bool{ diff --git a/src/pocketmine/network/mcpe/protocol/CraftingDataPacket.php b/src/pocketmine/network/mcpe/protocol/CraftingDataPacket.php index 776be76bd..27f59e73b 100644 --- a/src/pocketmine/network/mcpe/protocol/CraftingDataPacket.php +++ b/src/pocketmine/network/mcpe/protocol/CraftingDataPacket.php @@ -33,6 +33,9 @@ use pocketmine\item\Item; use pocketmine\item\ItemFactory; use pocketmine\network\mcpe\NetworkBinaryStream; use pocketmine\network\mcpe\NetworkSession; +#ifndef COMPILE +use pocketmine\utils\Binary; +#endif use function count; use function str_repeat; @@ -72,11 +75,13 @@ class CraftingDataPacket extends DataPacket{ 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"] = []; @@ -85,16 +90,19 @@ class CraftingDataPacket extends DataPacket{ } $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"] = []; @@ -103,6 +111,7 @@ class CraftingDataPacket extends DataPacket{ } $entry["uuid"] = $this->getUUID()->toString(); $entry["block"] = $this->getString(); + $entry["priority"] = $this->getVarInt(); break; case self::ENTRY_FURNACE: @@ -116,7 +125,10 @@ class CraftingDataPacket extends DataPacket{ } } $entry["input"] = ItemFactory::get($inputId, $inputData); - $entry["output"] = $this->getSlot(); + $entry["output"] = $out = $this->getSlot(); + if($out->getDamage() === 0x7fff){ + $out->setDamage(0); //TODO HACK: some 1.12 furnace recipe outputs have wildcard damage values + } $entry["block"] = $this->getString(); break; @@ -131,11 +143,11 @@ class CraftingDataPacket extends DataPacket{ $this->getBool(); //cleanRecipes } - private static function writeEntry($entry, NetworkBinaryStream $stream){ + private static function writeEntry($entry, NetworkBinaryStream $stream, int $pos){ 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); } @@ -144,10 +156,11 @@ class CraftingDataPacket extends DataPacket{ return -1; } - private static function writeShapelessRecipe(ShapelessRecipe $recipe, NetworkBinaryStream $stream){ + private static function writeShapelessRecipe(ShapelessRecipe $recipe, NetworkBinaryStream $stream, int $pos){ + $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(); @@ -158,17 +171,19 @@ class CraftingDataPacket extends DataPacket{ $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){ + private static function writeShapedRecipe(ShapedRecipe $recipe, NetworkBinaryStream $stream, int $pos){ + $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)); } } @@ -180,6 +195,7 @@ class CraftingDataPacket extends DataPacket{ $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; } @@ -212,8 +228,9 @@ class CraftingDataPacket extends DataPacket{ $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..6c2cbf74d --- /dev/null +++ b/src/pocketmine/network/mcpe/protocol/LevelChunkPacket.php @@ -0,0 +1,145 @@ + + +use function count; +use pocketmine\network\mcpe\NetworkSession; + +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(NetworkSession $handler) : bool{ + return $handler->handleLevelChunk($this); + } +} diff --git a/src/pocketmine/network/mcpe/protocol/LevelEventGenericPacket.php b/src/pocketmine/network/mcpe/protocol/LevelEventGenericPacket.php new file mode 100644 index 000000000..872a4d014 --- /dev/null +++ b/src/pocketmine/network/mcpe/protocol/LevelEventGenericPacket.php @@ -0,0 +1,74 @@ + + +use pocketmine\nbt\NetworkLittleEndianNBTStream; +use pocketmine\nbt\tag\CompoundTag; +use pocketmine\network\mcpe\NetworkSession; + +class LevelEventGenericPacket extends DataPacket/* implements ClientboundPacket*/{ + public const NETWORK_ID = ProtocolInfo::LEVEL_EVENT_GENERIC_PACKET; + + /** @var int */ + private $eventId; + /** @var string network-format NBT */ + private $eventData; + + public static function create(int $eventId, CompoundTag $data) : self{ + $result = new self; + $result->eventId = $eventId; + $result->eventData = (new NetworkLittleEndianNBTStream())->write($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->eventId = $this->getVarInt(); + $this->eventData = $this->getRemaining(); + } + + protected function encodePayload() : void{ + $this->putVarInt($this->eventId); + $this->put($this->eventData); + } + + public function handle(NetworkSession $handler) : bool{ + return $handler->handleLevelEventGeneric($this); + } +} diff --git a/src/pocketmine/network/mcpe/protocol/MoveEntityAbsolutePacket.php b/src/pocketmine/network/mcpe/protocol/MoveActorAbsolutePacket.php similarity index 91% rename from src/pocketmine/network/mcpe/protocol/MoveEntityAbsolutePacket.php rename to src/pocketmine/network/mcpe/protocol/MoveActorAbsolutePacket.php index 33a0ccbd0..8a7685593 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\NetworkSession; -class MoveEntityAbsolutePacket extends DataPacket{ - public const NETWORK_ID = ProtocolInfo::MOVE_ENTITY_ABSOLUTE_PACKET; +class MoveActorAbsolutePacket extends DataPacket{ + 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{ } public function handle(NetworkSession $session) : bool{ - return $session->handleMoveEntityAbsolute($this); + return $session->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 0430a8433..21ee91309 100644 --- a/src/pocketmine/network/mcpe/protocol/MoveEntityDeltaPacket.php +++ b/src/pocketmine/network/mcpe/protocol/MoveActorDeltaPacket.php @@ -27,8 +27,8 @@ namespace pocketmine\network\mcpe\protocol; use pocketmine\network\mcpe\NetworkSession; -class MoveEntityDeltaPacket extends DataPacket{ - public const NETWORK_ID = ProtocolInfo::MOVE_ENTITY_DELTA_PACKET; +class MoveActorDeltaPacket extends DataPacket{ + public const NETWORK_ID = ProtocolInfo::MOVE_ACTOR_DELTA_PACKET; public const FLAG_HAS_X = 0x01; public const FLAG_HAS_Y = 0x02; @@ -103,6 +103,6 @@ class MoveEntityDeltaPacket extends DataPacket{ } public function handle(NetworkSession $session) : bool{ - return $session->handleMoveEntityDelta($this); + return $session->handleMoveActorDelta($this); } } diff --git a/src/pocketmine/network/mcpe/protocol/PacketPool.php b/src/pocketmine/network/mcpe/protocol/PacketPool.php index f505d17ef..05c532d60 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..6173bee92 --- /dev/null +++ b/src/pocketmine/network/mcpe/protocol/RemoveActorPacket.php @@ -0,0 +1,48 @@ + + + +use pocketmine\network\mcpe\NetworkSession; + +class RemoveActorPacket extends DataPacket{ + public const NETWORK_ID = ProtocolInfo::REMOVE_ACTOR_PACKET; + + /** @var int */ + public $entityUniqueId; + + protected function decodePayload(){ + $this->entityUniqueId = $this->getEntityUniqueId(); + } + + protected function encodePayload(){ + $this->putEntityUniqueId($this->entityUniqueId); + } + + public function handle(NetworkSession $session) : bool{ + return $session->handleRemoveActor($this); + } +} diff --git a/src/pocketmine/network/mcpe/protocol/RemoveEntityPacket.php b/src/pocketmine/network/mcpe/protocol/RemoveEntityPacket.php index b4ef71361..82f50e158 100644 --- a/src/pocketmine/network/mcpe/protocol/RemoveEntityPacket.php +++ b/src/pocketmine/network/mcpe/protocol/RemoveEntityPacket.php @@ -25,24 +25,36 @@ namespace pocketmine\network\mcpe\protocol; #include - use pocketmine\network\mcpe\NetworkSession; -class RemoveEntityPacket extends DataPacket{ +class RemoveEntityPacket extends DataPacket/* implements ClientboundPacket*/{ public const NETWORK_ID = ProtocolInfo::REMOVE_ENTITY_PACKET; /** @var int */ - public $entityUniqueId; + private $uvarint1; - protected function decodePayload(){ - $this->entityUniqueId = $this->getEntityUniqueId(); + public static function create(int $uvarint1) : self{ + $result = new self; + $result->uvarint1 = $uvarint1; + return $result; } - protected function encodePayload(){ - $this->putEntityUniqueId($this->entityUniqueId); + /** + * @return int + */ + public function getUvarint1() : int{ + return $this->uvarint1; } - public function handle(NetworkSession $session) : bool{ - return $session->handleRemoveEntity($this); + protected function decodePayload() : void{ + $this->uvarint1 = $this->getUnsignedVarInt(); + } + + protected function encodePayload() : void{ + $this->putUnsignedVarInt($this->uvarint1); + } + + public function handle(NetworkSession $handler) : bool{ + return $handler->handleRemoveEntity($this); } } diff --git a/src/pocketmine/network/mcpe/protocol/ResourcePackDataInfoPacket.php b/src/pocketmine/network/mcpe/protocol/ResourcePackDataInfoPacket.php index a16bd9980..2e204e654 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{ public $compressedPackSize; /** @var string */ public $sha256; + /** @var bool */ + public $isPremium = false; + /** @var int */ + public $packType = 0; //TODO: check the values for this protected function decodePayload(){ $this->packId = $this->getString(); @@ -49,6 +53,8 @@ class ResourcePackDataInfoPacket extends DataPacket{ $this->chunkCount = $this->getLInt(); $this->compressedPackSize = $this->getLLong(); $this->sha256 = $this->getString(); + $this->isPremium = $this->getBool(); + $this->packType = $this->getByte(); } protected function encodePayload(){ @@ -57,6 +63,8 @@ class ResourcePackDataInfoPacket extends DataPacket{ $this->putLInt($this->chunkCount); $this->putLLong($this->compressedPackSize); $this->putString($this->sha256); + $this->putBool($this->isPremium); + $this->putByte($this->packType); } public function handle(NetworkSession $session) : bool{ diff --git a/src/pocketmine/network/mcpe/protocol/SetEntityDataPacket.php b/src/pocketmine/network/mcpe/protocol/SetActorDataPacket.php similarity index 89% rename from src/pocketmine/network/mcpe/protocol/SetEntityDataPacket.php rename to src/pocketmine/network/mcpe/protocol/SetActorDataPacket.php index 678cfda61..de9639e7a 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\NetworkSession; -class SetEntityDataPacket extends DataPacket{ - public const NETWORK_ID = ProtocolInfo::SET_ENTITY_DATA_PACKET; +class SetActorDataPacket extends DataPacket{ + public const NETWORK_ID = ProtocolInfo::SET_ACTOR_DATA_PACKET; /** @var int */ public $entityRuntimeId; @@ -47,6 +47,6 @@ class SetEntityDataPacket extends DataPacket{ } public function handle(NetworkSession $session) : bool{ - return $session->handleSetEntityData($this); + return $session->handleSetActorData($this); } } diff --git a/src/pocketmine/network/mcpe/protocol/SetEntityLinkPacket.php b/src/pocketmine/network/mcpe/protocol/SetActorLinkPacket.php similarity index 88% rename from src/pocketmine/network/mcpe/protocol/SetEntityLinkPacket.php rename to src/pocketmine/network/mcpe/protocol/SetActorLinkPacket.php index 63928b9b1..da8acbf58 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\NetworkSession; use pocketmine\network\mcpe\protocol\types\EntityLink; -class SetEntityLinkPacket extends DataPacket{ - public const NETWORK_ID = ProtocolInfo::SET_ENTITY_LINK_PACKET; +class SetActorLinkPacket extends DataPacket{ + public const NETWORK_ID = ProtocolInfo::SET_ACTOR_LINK_PACKET; /** @var EntityLink */ public $link; @@ -44,6 +44,6 @@ class SetEntityLinkPacket extends DataPacket{ } public function handle(NetworkSession $session) : bool{ - return $session->handleSetEntityLink($this); + return $session->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 66b217552..af2f3199d 100644 --- a/src/pocketmine/network/mcpe/protocol/SetEntityMotionPacket.php +++ b/src/pocketmine/network/mcpe/protocol/SetActorMotionPacket.php @@ -29,8 +29,8 @@ namespace pocketmine\network\mcpe\protocol; use pocketmine\math\Vector3; use pocketmine\network\mcpe\NetworkSession; -class SetEntityMotionPacket extends DataPacket{ - public const NETWORK_ID = ProtocolInfo::SET_ENTITY_MOTION_PACKET; +class SetActorMotionPacket extends DataPacket{ + public const NETWORK_ID = ProtocolInfo::SET_ACTOR_MOTION_PACKET; /** @var int */ public $entityRuntimeId; @@ -48,6 +48,6 @@ class SetEntityMotionPacket extends DataPacket{ } public function handle(NetworkSession $session) : bool{ - return $session->handleSetEntityMotion($this); + return $session->handleSetActorMotion($this); } } diff --git a/src/pocketmine/network/mcpe/protocol/StartGamePacket.php b/src/pocketmine/network/mcpe/protocol/StartGamePacket.php index 4894d8acf..e9a7f1003 100644 --- a/src/pocketmine/network/mcpe/protocol/StartGamePacket.php +++ b/src/pocketmine/network/mcpe/protocol/StartGamePacket.php @@ -26,18 +26,24 @@ namespace pocketmine\network\mcpe\protocol; #include +use function file_get_contents; +use function json_decode; use pocketmine\math\Vector3; use pocketmine\network\mcpe\NetworkBinaryStream; use pocketmine\network\mcpe\NetworkSession; use pocketmine\network\mcpe\protocol\types\PlayerPermissions; use pocketmine\network\mcpe\protocol\types\RuntimeBlockMapping; use function count; +use pocketmine\network\mcpe\protocol\types\RuntimeItemMapping; +use const pocketmine\RESOURCE_PATH; class StartGamePacket extends DataPacket{ 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 +128,8 @@ class StartGamePacket extends DataPacket{ 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 +146,10 @@ class StartGamePacket extends DataPacket{ /** @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(){ $this->entityUniqueId = $this->getEntityUniqueId(); @@ -185,6 +192,7 @@ class StartGamePacket extends DataPacket{ $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 +202,23 @@ class StartGamePacket extends DataPacket{ $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(){ @@ -249,6 +262,7 @@ class StartGamePacket extends DataPacket{ $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 +272,25 @@ class StartGamePacket extends DataPacket{ $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 +299,17 @@ class StartGamePacket extends DataPacket{ 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..b1cebc172 --- /dev/null +++ b/src/pocketmine/network/mcpe/protocol/StructureTemplateDataExportRequestPacket.php @@ -0,0 +1,44 @@ + + +use pocketmine\network\mcpe\NetworkSession; + +class StructureTemplateDataExportRequestPacket extends DataPacket{ + public const NETWORK_ID = ProtocolInfo::STRUCTURE_TEMPLATE_DATA_EXPORT_REQUEST_PACKET; + + protected function decodePayload() : void{ + //TODO + } + + protected function encodePayload() : void{ + //TODO + } + + public function handle(NetworkSession $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..b3878fd64 --- /dev/null +++ b/src/pocketmine/network/mcpe/protocol/StructureTemplateDataExportResponsePacket.php @@ -0,0 +1,44 @@ + + +use pocketmine\network\mcpe\NetworkSession; + +class StructureTemplateDataExportResponsePacket extends DataPacket{ + public const NETWORK_ID = ProtocolInfo::STRUCTURE_TEMPLATE_DATA_EXPORT_RESPONSE_PACKET; + + protected function decodePayload() : void{ + //TODO + } + + protected function encodePayload() : void{ + //TODO + } + + public function handle(NetworkSession $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 608cc0317..173911e05 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\NetworkSession; -class TakeItemEntityPacket extends DataPacket{ - public const NETWORK_ID = ProtocolInfo::TAKE_ITEM_ENTITY_PACKET; +class TakeItemActorPacket extends DataPacket{ + public const NETWORK_ID = ProtocolInfo::TAKE_ITEM_ACTOR_PACKET; /** @var int */ public $target; @@ -47,6 +47,6 @@ class TakeItemEntityPacket extends DataPacket{ } public function handle(NetworkSession $session) : bool{ - return $session->handleTakeItemEntity($this); + return $session->handleTakeItemActor($this); } } diff --git a/src/pocketmine/network/mcpe/protocol/FullChunkDataPacket.php b/src/pocketmine/network/mcpe/protocol/UpdateBlockPropertiesPacket.php similarity index 57% rename from src/pocketmine/network/mcpe/protocol/FullChunkDataPacket.php rename to src/pocketmine/network/mcpe/protocol/UpdateBlockPropertiesPacket.php index c3c0a4215..f29d2b464 100644 --- a/src/pocketmine/network/mcpe/protocol/FullChunkDataPacket.php +++ b/src/pocketmine/network/mcpe/protocol/UpdateBlockPropertiesPacket.php @@ -25,32 +25,31 @@ namespace pocketmine\network\mcpe\protocol; #include - +use pocketmine\nbt\NetworkLittleEndianNBTStream; +use pocketmine\nbt\tag\CompoundTag; use pocketmine\network\mcpe\NetworkSession; -class FullChunkDataPacket extends DataPacket{ - public const NETWORK_ID = ProtocolInfo::FULL_CHUNK_DATA_PACKET; +class UpdateBlockPropertiesPacket extends DataPacket{ + public const NETWORK_ID = ProtocolInfo::UPDATE_BLOCK_PROPERTIES_PACKET; - /** @var int */ - public $chunkX; - /** @var int */ - public $chunkZ; /** @var string */ - public $data; + private $nbt; - protected function decodePayload(){ - $this->chunkX = $this->getVarInt(); - $this->chunkZ = $this->getVarInt(); - $this->data = $this->getString(); + public static function create(CompoundTag $data) : self{ + $result = new self; + $result->nbt = (new NetworkLittleEndianNBTStream())->write($data); + return $result; } - protected function encodePayload(){ - $this->putVarInt($this->chunkX); - $this->putVarInt($this->chunkZ); - $this->putString($this->data); + protected function decodePayload() : void{ + $this->nbt = $this->getRemaining(); } - public function handle(NetworkSession $session) : bool{ - return $session->handleFullChunkData($this); + protected function encodePayload() : void{ + $this->put($this->nbt); + } + + public function handle(NetworkSession $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 507d135a9..aed7d1c54 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(NetworkSession $session) : 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/RuntimeBlockMapping.php b/src/pocketmine/network/mcpe/protocol/types/RuntimeBlockMapping.php index 758b786af..9ba73cbb4 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/resources/vanilla b/src/pocketmine/resources/vanilla index 7d9cec886..b5a8c68c4 160000 --- a/src/pocketmine/resources/vanilla +++ b/src/pocketmine/resources/vanilla @@ -1 +1 @@ -Subproject commit 7d9cec8861a9de033da78bb133f8159f2dfd41c5 +Subproject commit b5a8c68c4262e5d9d7f8280c1d07c252a5e8dbf8 diff --git a/src/pocketmine/tile/Spawnable.php b/src/pocketmine/tile/Spawnable.php index 5f7802b31..bcad010b5 100644 --- a/src/pocketmine/tile/Spawnable.php +++ b/src/pocketmine/tile/Spawnable.php @@ -28,7 +28,7 @@ use pocketmine\nbt\NetworkLittleEndianNBTStream; use pocketmine\nbt\tag\CompoundTag; use pocketmine\nbt\tag\IntTag; use pocketmine\nbt\tag\StringTag; -use pocketmine\network\mcpe\protocol\BlockEntityDataPacket; +use pocketmine\network\mcpe\protocol\BlockActorDataPacket; use pocketmine\Player; abstract class Spawnable extends Tile{ @@ -37,8 +37,8 @@ abstract class Spawnable extends Tile{ /** @var NetworkLittleEndianNBTStream|null */ private static $nbtWriter = null; - public function createSpawnPacket() : BlockEntityDataPacket{ - $pk = new BlockEntityDataPacket(); + public function createSpawnPacket() : BlockActorDataPacket{ + $pk = new BlockActorDataPacket(); $pk->x = $this->x; $pk->y = $this->y; $pk->z = $this->z;