diff --git a/src/pocketmine/Player.php b/src/pocketmine/Player.php index d623805ce..5c0ac0a95 100644 --- a/src/pocketmine/Player.php +++ b/src/pocketmine/Player.php @@ -116,6 +116,7 @@ use pocketmine\network\mcpe\protocol\BlockEntityDataPacket; use pocketmine\network\mcpe\protocol\BlockEventPacket; use pocketmine\network\mcpe\protocol\ChangeDimensionPacket; use pocketmine\network\mcpe\protocol\ChunkRadiusUpdatedPacket; +use pocketmine\network\mcpe\protocol\ClientboundMapItemDataPacket; use pocketmine\network\mcpe\protocol\ClientToServerHandshakePacket; use pocketmine\network\mcpe\protocol\CommandStepPacket; use pocketmine\network\mcpe\protocol\ContainerClosePacket; @@ -132,14 +133,13 @@ use pocketmine\network\mcpe\protocol\EntityEventPacket; use pocketmine\network\mcpe\protocol\ExplodePacket; use pocketmine\network\mcpe\protocol\FullChunkDataPacket; use pocketmine\network\mcpe\protocol\HurtArmorPacket; -use pocketmine\network\mcpe\protocol\MapInfoRequestPacket; -use pocketmine\network\mcpe\protocol\ProtocolInfo; use pocketmine\network\mcpe\protocol\InteractPacket; use pocketmine\network\mcpe\protocol\InventoryActionPacket; use pocketmine\network\mcpe\protocol\ItemFrameDropItemPacket; use pocketmine\network\mcpe\protocol\LevelEventPacket; use pocketmine\network\mcpe\protocol\LevelSoundEventPacket; use pocketmine\network\mcpe\protocol\LoginPacket; +use pocketmine\network\mcpe\protocol\MapInfoRequestPacket; use pocketmine\network\mcpe\protocol\MobArmorEquipmentPacket; use pocketmine\network\mcpe\protocol\MobEffectPacket; use pocketmine\network\mcpe\protocol\MobEquipmentPacket; @@ -150,6 +150,7 @@ use pocketmine\network\mcpe\protocol\PlayerFallPacket; use pocketmine\network\mcpe\protocol\PlayerInputPacket; use pocketmine\network\mcpe\protocol\PlayerListPacket; use pocketmine\network\mcpe\protocol\PlayStatusPacket; +use pocketmine\network\mcpe\protocol\ProtocolInfo; use pocketmine\network\mcpe\protocol\RemoveBlockPacket; use pocketmine\network\mcpe\protocol\RemoveEntityPacket; use pocketmine\network\mcpe\protocol\ReplaceItemInSlotPacket; @@ -186,7 +187,6 @@ use pocketmine\network\SourceInterface; use pocketmine\permission\PermissibleBase; use pocketmine\permission\PermissionAttachment; use pocketmine\plugin\Plugin; -use pocketmine\resourcepacks\ResourcePackInfoEntry; use pocketmine\tile\ItemFrame; use pocketmine\tile\Spawnable; use pocketmine\utils\TextFormat; @@ -3204,6 +3204,10 @@ class Player extends Human implements CommandSender, InventoryHolder, ChunkLoade return false; //TODO } + public function handleClientboundMapItemData(ClientboundMapItemDataPacket $packet) : bool{ + return false; + } + public function handleMapInfoRequest(MapInfoRequestPacket $packet) : bool{ return false; //TODO } diff --git a/src/pocketmine/network/Network.php b/src/pocketmine/network/Network.php index 663d7de36..4f5dda94a 100644 --- a/src/pocketmine/network/Network.php +++ b/src/pocketmine/network/Network.php @@ -38,6 +38,7 @@ use pocketmine\network\mcpe\protocol\BlockEntityDataPacket; use pocketmine\network\mcpe\protocol\BlockEventPacket; use pocketmine\network\mcpe\protocol\ChangeDimensionPacket; use pocketmine\network\mcpe\protocol\ChunkRadiusUpdatedPacket; +use pocketmine\network\mcpe\protocol\ClientboundMapItemDataPacket; use pocketmine\network\mcpe\protocol\ClientToServerHandshakePacket; use pocketmine\network\mcpe\protocol\CommandStepPacket; use pocketmine\network\mcpe\protocol\ContainerClosePacket; @@ -328,6 +329,7 @@ class Network{ $this->registerPacket(ProtocolInfo::BLOCK_EVENT_PACKET, BlockEventPacket::class); $this->registerPacket(ProtocolInfo::CHANGE_DIMENSION_PACKET, ChangeDimensionPacket::class); $this->registerPacket(ProtocolInfo::CHUNK_RADIUS_UPDATED_PACKET, ChunkRadiusUpdatedPacket::class); + $this->registerPacket(ProtocolInfo::CLIENTBOUND_MAP_ITEM_DATA_PACKET, ClientboundMapItemDataPacket::class); $this->registerPacket(ProtocolInfo::CLIENT_TO_SERVER_HANDSHAKE_PACKET, ClientToServerHandshakePacket::class); $this->registerPacket(ProtocolInfo::COMMAND_STEP_PACKET, CommandStepPacket::class); $this->registerPacket(ProtocolInfo::CONTAINER_CLOSE_PACKET, ContainerClosePacket::class); diff --git a/src/pocketmine/network/mcpe/NetworkSession.php b/src/pocketmine/network/mcpe/NetworkSession.php index 62b12647e..62786b8f2 100644 --- a/src/pocketmine/network/mcpe/NetworkSession.php +++ b/src/pocketmine/network/mcpe/NetworkSession.php @@ -37,6 +37,7 @@ use pocketmine\network\mcpe\protocol\BlockEntityDataPacket; use pocketmine\network\mcpe\protocol\BlockEventPacket; use pocketmine\network\mcpe\protocol\ChangeDimensionPacket; use pocketmine\network\mcpe\protocol\ChunkRadiusUpdatedPacket; +use pocketmine\network\mcpe\protocol\ClientboundMapItemDataPacket; use pocketmine\network\mcpe\protocol\ClientToServerHandshakePacket; use pocketmine\network\mcpe\protocol\CommandStepPacket; use pocketmine\network\mcpe\protocol\ContainerClosePacket; @@ -234,7 +235,7 @@ interface NetworkSession{ public function handleSpawnExperienceOrb(SpawnExperienceOrbPacket $packet) : bool; - //public function handleClientboundMapItemData(ClientboundMapItemDataPacket $packet) : bool; //TODO + public function handleClientboundMapItemData(ClientboundMapItemDataPacket $packet) : bool; public function handleMapInfoRequest(MapInfoRequestPacket $packet) : bool; //TODO diff --git a/src/pocketmine/network/mcpe/protocol/ClientboundMapItemDataPacket.php b/src/pocketmine/network/mcpe/protocol/ClientboundMapItemDataPacket.php new file mode 100644 index 000000000..86f28fae8 --- /dev/null +++ b/src/pocketmine/network/mcpe/protocol/ClientboundMapItemDataPacket.php @@ -0,0 +1,149 @@ + + + +use pocketmine\network\mcpe\NetworkSession; +use pocketmine\utils\Color; + +class ClientboundMapItemDataPacket extends DataPacket{ + const NETWORK_ID = ProtocolInfo::CLIENTBOUND_MAP_ITEM_DATA_PACKET; + + const BITFLAG_TEXTURE_UPDATE = 0x02; + const BITFLAG_DECORATION_UPDATE = 0x04; + + public $mapId; + public $type; + + public $eids = []; + public $scale; + public $decorations = []; + + public $width; + public $height; + public $xOffset = 0; + public $yOffset = 0; + /** @var Color[][] */ + public $colors = []; + + public function decode(){ + $this->mapId = $this->getVarInt(); + $this->type = $this->getUnsignedVarInt(); + + if(($this->type & 0x08) !== 0){ + $count = $this->getUnsignedVarInt(); + for($i = 0; $i < $count; ++$i){ + $this->eids[] = $this->getVarInt(); //entity unique ID, signed var-int + } + } + + if(($this->type & (self::BITFLAG_DECORATION_UPDATE | self::BITFLAG_TEXTURE_UPDATE)) !== 0){ //Decoration bitflag or colour bitflag + $this->scale = $this->getByte(); + } + + if(($this->type & self::BITFLAG_DECORATION_UPDATE) !== 0){ + $count = $this->getUnsignedVarInt(); + for($i = 0; $i < $count; ++$i){ + $weird = $this->getVarInt(); + $this->decorations[$i]["rot"] = $weird & 0x0f; + $this->decorations[$i]["img"] = $weird >> 4; + + $this->decorations[$i]["xOffset"] = $this->getByte(); + $this->decorations[$i]["yOffset"] = $this->getByte(); + $this->decorations[$i]["label"] = $this->getString(); + + $this->decorations[$i]["color"] = Color::fromARGB($this->getLInt()); //already BE, don't need to reverse it again + } + } + + if(($this->type & self::BITFLAG_TEXTURE_UPDATE) !== 0){ + $this->width = $this->getVarInt(); + $this->height = $this->getVarInt(); + $this->xOffset = $this->getVarInt(); + $this->yOffset = $this->getVarInt(); + for($y = 0; $y < $this->height; ++$y){ + for($x = 0; $x < $this->width; ++$x){ + $this->colors[$y][$x] = Color::fromABGR($this->getUnsignedVarInt()); + } + } + } + } + + public function encode(){ + $this->reset(); + $this->putVarInt($this->mapId); //entity unique ID, signed var-int + + $type = 0; + if(($eidsCount = count($this->eids)) > 0){ + $type |= 0x08; + } + if(($decorationCount = count($this->decorations)) > 0){ + $type |= self::BITFLAG_DECORATION_UPDATE; + } + if(count($this->colors) > 0){ + $type |= self::BITFLAG_TEXTURE_UPDATE; + } + + $this->putUnsignedVarInt($type); + + if(($type & 0x08) !== 0){ //TODO: find out what these are for + $this->putUnsignedVarInt($eidsCount); + foreach($this->eids as $eid){ + $this->putVarInt($eid); + } + } + + if(($type & (self::BITFLAG_TEXTURE_UPDATE | self::BITFLAG_DECORATION_UPDATE)) !== 0){ + $this->putByte($this->scale); + } + + if(($type & self::BITFLAG_DECORATION_UPDATE) !== 0){ + $this->putUnsignedVarInt($decorationCount); + foreach($this->decorations as $decoration){ + $this->putVarInt(($decoration["rot"] & 0x0f) | ($decoration["img"] << 4)); + $this->putByte($decoration["xOffset"]); + $this->putByte($decoration["yOffset"]); + $this->putString($decoration["label"]); + $this->putLInt($decoration["color"]->toARGB()); + } + } + + if(($type & self::BITFLAG_TEXTURE_UPDATE) !== 0){ + $this->putVarInt($this->width); + $this->putVarInt($this->height); + $this->putVarInt($this->xOffset); + $this->putVarInt($this->yOffset); + for($y = 0; $y < $this->height; ++$y){ + for($x = 0; $x < $this->width; ++$x){ + $this->putUnsignedVarInt($this->colors[$y][$x]->toABGR()); + } + } + } + } + + public function handle(NetworkSession $session) : bool{ + $session->handleClientboundMapItemData($this); + } +} \ No newline at end of file diff --git a/src/pocketmine/utils/Color.php b/src/pocketmine/utils/Color.php new file mode 100644 index 000000000..6913e7a92 --- /dev/null +++ b/src/pocketmine/utils/Color.php @@ -0,0 +1,158 @@ +r = $r & 0xff; + $this->g = $g & 0xff; + $this->b = $b & 0xff; + $this->a = $a & 0xff; + } + + /** + * Returns the alpha (transparency) value of this colour. + * @return int + */ + public function getA() : int{ + return $this->a; + } + + /** + * Sets the alpha (opacity) value of this colour, lower = more transparent + * @param int $a + */ + public function setA(int $a){ + $this->a = $a & 0xff; + } + + /** + * Retuns the red value of this colour. + * @return int + */ + public function getR() : int{ + return $this->r; + } + + /** + * Sets the red value of this colour. + * @param int $r + */ + public function setR(int $r){ + $this->r = $r & 0xff; + } + + /** + * Returns the green value of this colour. + * @return int + */ + public function getG() : int{ + return $this->g; + } + + /** + * Sets the green value of this colour. + * @param int $g + */ + public function setG(int $g){ + $this->g = $g & 0xff; + } + + /** + * Returns the blue value of this colour. + * @return int + */ + public function getB() : int{ + return $this->b; + } + + /** + * Sets the blue value of this colour. + * @param int $b + */ + public function setB(int $b){ + $this->b = $b & 0xff; + } + + /** + * Returns a Color from the supplied RGB colour code (24-bit) + * @param int $code + * + * @return Color + */ + public static function fromRGB(int $code){ + return new Color(($code >> 16) & 0xff, ($code >> 8) & 0xff, $code & 0xff); + } + + /** + * Returns a Color from the supplied ARGB colour code (32-bit) + * + * @param int $code + * + * @return Color + */ + public static function fromARGB(int $code){ + return new Color(($code >> 16) & 0xff, ($code >> 8) & 0xff, $code & 0xff, ($code >> 24) & 0xff); + } + + /** + * Returns an ARGB 32-bit colour value. + * @return int + */ + public function toARGB() : int{ + return ($this->a << 24) | ($this->r << 16) | ($this->g << 8) | $this->b; + } + + /** + * Returns a little-endian ARGB 32-bit colour value. + * @return int + */ + public function toBGRA() : int{ + return ($this->b << 24) | ($this->g << 16) | ($this->r << 8) | $this->a; + } + + /** + * Returns an RGBA 32-bit colour value. + * @return int + */ + public function toRGBA() : int{ + return ($this->r << 24) | ($this->g << 16) | ($this->b << 8) | $this->a; + } + + /** + * Returns a little-endian RGBA colour value. + * @return int + */ + public function toABGR() : int{ + return ($this->a << 24) | ($this->b << 16) | ($this->g << 8) | $this->r; + } + + public static function fromABGR(int $code){ + return new Color($code & 0xff, ($code >> 8) & 0xff, ($code >> 16) & 0xff, ($code >> 24) & 0xff); + } +} \ No newline at end of file