PocketMine-MP 5.15.1 git-08c6e63aac45a450fe3b437616ee8aa2500e04e2
ClientboundMapItemDataPacket.php
1<?php
2
3/*
4 * This file is part of BedrockProtocol.
5 * Copyright (C) 2014-2022 PocketMine Team <https://github.com/pmmp/BedrockProtocol>
6 *
7 * BedrockProtocol is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 */
12
13declare(strict_types=1);
14
15namespace pocketmine\network\mcpe\protocol;
16
25use function count;
26
28 public const NETWORK_ID = ProtocolInfo::CLIENTBOUND_MAP_ITEM_DATA_PACKET;
29
30 public const BITFLAG_TEXTURE_UPDATE = 0x02;
31 public const BITFLAG_DECORATION_UPDATE = 0x04;
32 public const BITFLAG_MAP_CREATION = 0x08;
33
34 public int $mapId;
35 public int $type;
36 public int $dimensionId = DimensionIds::OVERWORLD;
37 public bool $isLocked = false;
38 public BlockPosition $origin;
39
41 public array $parentMapIds = [];
42 public int $scale;
43
45 public array $trackedEntities = [];
47 public array $decorations = [];
48
49 public int $xOffset = 0;
50 public int $yOffset = 0;
51 public ?MapImage $colors = null;
52
53 protected function decodePayload(PacketSerializer $in) : void{
54 $this->mapId = $in->getActorUniqueId();
55 $this->type = $in->getUnsignedVarInt();
56 $this->dimensionId = $in->getByte();
57 $this->isLocked = $in->getBool();
58 $this->origin = $in->getSignedBlockPosition();
59
60 if(($this->type & self::BITFLAG_MAP_CREATION) !== 0){
61 $count = $in->getUnsignedVarInt();
62 for($i = 0; $i < $count; ++$i){
63 $this->parentMapIds[] = $in->getActorUniqueId();
64 }
65 }
66
67 if(($this->type & (self::BITFLAG_MAP_CREATION | self::BITFLAG_DECORATION_UPDATE | self::BITFLAG_TEXTURE_UPDATE)) !== 0){ //Decoration bitflag or colour bitflag
68 $this->scale = $in->getByte();
69 }
70
71 if(($this->type & self::BITFLAG_DECORATION_UPDATE) !== 0){
72 for($i = 0, $count = $in->getUnsignedVarInt(); $i < $count; ++$i){
73 $object = new MapTrackedObject();
74 $object->type = $in->getLInt();
75 if($object->type === MapTrackedObject::TYPE_BLOCK){
76 $object->blockPosition = $in->getBlockPosition();
77 }elseif($object->type === MapTrackedObject::TYPE_ENTITY){
78 $object->actorUniqueId = $in->getActorUniqueId();
79 }else{
80 throw new PacketDecodeException("Unknown map object type $object->type");
81 }
82 $this->trackedEntities[] = $object;
83 }
84
85 for($i = 0, $count = $in->getUnsignedVarInt(); $i < $count; ++$i){
86 $icon = $in->getByte();
87 $rotation = $in->getByte();
88 $xOffset = $in->getByte();
89 $yOffset = $in->getByte();
90 $label = $in->getString();
91 $color = Color::fromRGBA(Binary::flipIntEndianness($in->getUnsignedVarInt()));
92 $this->decorations[] = new MapDecoration($icon, $rotation, $xOffset, $yOffset, $label, $color);
93 }
94 }
95
96 if(($this->type & self::BITFLAG_TEXTURE_UPDATE) !== 0){
97 $width = $in->getVarInt();
98 $height = $in->getVarInt();
99 $this->xOffset = $in->getVarInt();
100 $this->yOffset = $in->getVarInt();
101
102 $count = $in->getUnsignedVarInt();
103 if($count !== $width * $height){
104 throw new PacketDecodeException("Expected colour count of " . ($height * $width) . " (height $height * width $width), got $count");
105 }
106
107 $this->colors = MapImage::decode($in, $height, $width);
108 }
109 }
110
111 protected function encodePayload(PacketSerializer $out) : void{
112 $out->putActorUniqueId($this->mapId);
113
114 $type = 0;
115 if(($parentMapIdsCount = count($this->parentMapIds)) > 0){
116 $type |= self::BITFLAG_MAP_CREATION;
117 }
118 if(($decorationCount = count($this->decorations)) > 0){
119 $type |= self::BITFLAG_DECORATION_UPDATE;
120 }
121 if($this->colors !== null){
122 $type |= self::BITFLAG_TEXTURE_UPDATE;
123 }
124
125 $out->putUnsignedVarInt($type);
126 $out->putByte($this->dimensionId);
127 $out->putBool($this->isLocked);
128 $out->putSignedBlockPosition($this->origin);
129
130 if(($type & self::BITFLAG_MAP_CREATION) !== 0){
131 $out->putUnsignedVarInt($parentMapIdsCount);
132 foreach($this->parentMapIds as $parentMapId){
133 $out->putActorUniqueId($parentMapId);
134 }
135 }
136
137 if(($type & (self::BITFLAG_MAP_CREATION | self::BITFLAG_TEXTURE_UPDATE | self::BITFLAG_DECORATION_UPDATE)) !== 0){
138 $out->putByte($this->scale);
139 }
140
141 if(($type & self::BITFLAG_DECORATION_UPDATE) !== 0){
142 $out->putUnsignedVarInt(count($this->trackedEntities));
143 foreach($this->trackedEntities as $object){
144 $out->putLInt($object->type);
145 if($object->type === MapTrackedObject::TYPE_BLOCK){
146 $out->putBlockPosition($object->blockPosition);
147 }elseif($object->type === MapTrackedObject::TYPE_ENTITY){
148 $out->putActorUniqueId($object->actorUniqueId);
149 }else{
150 throw new \InvalidArgumentException("Unknown map object type $object->type");
151 }
152 }
153
154 $out->putUnsignedVarInt($decorationCount);
155 foreach($this->decorations as $decoration){
156 $out->putByte($decoration->getIcon());
157 $out->putByte($decoration->getRotation());
158 $out->putByte($decoration->getXOffset());
159 $out->putByte($decoration->getYOffset());
160 $out->putString($decoration->getLabel());
161 $out->putUnsignedVarInt(Binary::flipIntEndianness($decoration->getColor()->toRGBA()));
162 }
163 }
164
165 if($this->colors !== null){
166 $out->putVarInt($this->colors->getWidth());
167 $out->putVarInt($this->colors->getHeight());
168 $out->putVarInt($this->xOffset);
169 $out->putVarInt($this->yOffset);
170
171 $out->putUnsignedVarInt($this->colors->getWidth() * $this->colors->getHeight()); //list count, but we handle it as a 2D array... thanks for the confusion mojang
172
173 $this->colors->encode($out);
174 }
175 }
176
177 public function handle(PacketHandlerInterface $handler) : bool{
178 return $handler->handleClientboundMapItemData($this);
179 }
180}
static fromRGBA(int $code)
Definition: Color.php:115
static decode(BinaryStream $input, int $height, int $width)
Definition: MapImage.php:94