PocketMine-MP 5.35.1 git-e32e836dad793a3a3c8ddd8927c00e112b1e576a
Loading...
Searching...
No Matches
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
17use pmmp\encoding\Byte;
18use pmmp\encoding\ByteBufferReader;
19use pmmp\encoding\ByteBufferWriter;
20use pmmp\encoding\LE;
21use pmmp\encoding\VarInt;
30use function count;
31
33 public const NETWORK_ID = ProtocolInfo::CLIENTBOUND_MAP_ITEM_DATA_PACKET;
34
35 public const BITFLAG_TEXTURE_UPDATE = 0x02;
36 public const BITFLAG_DECORATION_UPDATE = 0x04;
37 public const BITFLAG_MAP_CREATION = 0x08;
38
39 public int $mapId;
40 public int $type;
41 public int $dimensionId = DimensionIds::OVERWORLD;
42 public bool $isLocked = false;
43 public BlockPosition $origin;
44
46 public array $parentMapIds = [];
47 public int $scale;
48
50 public array $trackedEntities = [];
52 public array $decorations = [];
53
54 public int $xOffset = 0;
55 public int $yOffset = 0;
56 public ?MapImage $colors = null;
57
58 protected function decodePayload(ByteBufferReader $in) : void{
59 $this->mapId = CommonTypes::getActorUniqueId($in);
60 $this->type = VarInt::readUnsignedInt($in);
61 $this->dimensionId = Byte::readUnsigned($in);
62 $this->isLocked = CommonTypes::getBool($in);
63 $this->origin = CommonTypes::getSignedBlockPosition($in);
64
65 if(($this->type & self::BITFLAG_MAP_CREATION) !== 0){
66 $count = VarInt::readUnsignedInt($in);
67 for($i = 0; $i < $count; ++$i){
68 $this->parentMapIds[] = CommonTypes::getActorUniqueId($in);
69 }
70 }
71
72 if(($this->type & (self::BITFLAG_MAP_CREATION | self::BITFLAG_DECORATION_UPDATE | self::BITFLAG_TEXTURE_UPDATE)) !== 0){ //Decoration bitflag or colour bitflag
73 $this->scale = Byte::readUnsigned($in);
74 }
75
76 if(($this->type & self::BITFLAG_DECORATION_UPDATE) !== 0){
77 for($i = 0, $count = VarInt::readUnsignedInt($in); $i < $count; ++$i){
78 $object = new MapTrackedObject();
79 $object->type = LE::readUnsignedInt($in);
80 if($object->type === MapTrackedObject::TYPE_BLOCK){
81 $object->blockPosition = CommonTypes::getBlockPosition($in);
82 }elseif($object->type === MapTrackedObject::TYPE_ENTITY){
83 $object->actorUniqueId = CommonTypes::getActorUniqueId($in);
84 }else{
85 throw new PacketDecodeException("Unknown map object type $object->type");
86 }
87 $this->trackedEntities[] = $object;
88 }
89
90 for($i = 0, $count = VarInt::readUnsignedInt($in); $i < $count; ++$i){
91 $icon = Byte::readUnsigned($in);
92 $rotation = Byte::readUnsigned($in);
93 $xOffset = Byte::readUnsigned($in);
94 $yOffset = Byte::readUnsigned($in);
95 $label = CommonTypes::getString($in);
96 $color = Color::fromRGBA(Binary::flipIntEndianness(VarInt::readUnsignedInt($in)));
97 $this->decorations[] = new MapDecoration($icon, $rotation, $xOffset, $yOffset, $label, $color);
98 }
99 }
100
101 if(($this->type & self::BITFLAG_TEXTURE_UPDATE) !== 0){
102 $width = VarInt::readSignedInt($in);
103 $height = VarInt::readSignedInt($in);
104 $this->xOffset = VarInt::readSignedInt($in);
105 $this->yOffset = VarInt::readSignedInt($in);
106
107 $count = VarInt::readUnsignedInt($in);
108 if($count !== $width * $height){
109 throw new PacketDecodeException("Expected colour count of " . ($height * $width) . " (height $height * width $width), got $count");
110 }
111
112 $this->colors = MapImage::decode($in, $height, $width);
113 }
114 }
115
116 protected function encodePayload(ByteBufferWriter $out) : void{
117 CommonTypes::putActorUniqueId($out, $this->mapId);
118
119 $type = 0;
120 if(($parentMapIdsCount = count($this->parentMapIds)) > 0){
121 $type |= self::BITFLAG_MAP_CREATION;
122 }
123 if(($decorationCount = count($this->decorations)) > 0){
124 $type |= self::BITFLAG_DECORATION_UPDATE;
125 }
126 if($this->colors !== null){
127 $type |= self::BITFLAG_TEXTURE_UPDATE;
128 }
129
130 VarInt::writeUnsignedInt($out, $type);
131 Byte::writeUnsigned($out, $this->dimensionId);
132 CommonTypes::putBool($out, $this->isLocked);
133 CommonTypes::putSignedBlockPosition($out, $this->origin);
134
135 if(($type & self::BITFLAG_MAP_CREATION) !== 0){
136 VarInt::writeUnsignedInt($out, $parentMapIdsCount);
137 foreach($this->parentMapIds as $parentMapId){
138 CommonTypes::putActorUniqueId($out, $parentMapId);
139 }
140 }
141
142 if(($type & (self::BITFLAG_MAP_CREATION | self::BITFLAG_TEXTURE_UPDATE | self::BITFLAG_DECORATION_UPDATE)) !== 0){
143 Byte::writeUnsigned($out, $this->scale);
144 }
145
146 if(($type & self::BITFLAG_DECORATION_UPDATE) !== 0){
147 VarInt::writeUnsignedInt($out, count($this->trackedEntities));
148 foreach($this->trackedEntities as $object){
149 LE::writeUnsignedInt($out, $object->type);
150 if($object->type === MapTrackedObject::TYPE_BLOCK){
151 CommonTypes::putBlockPosition($out, $object->blockPosition);
152 }elseif($object->type === MapTrackedObject::TYPE_ENTITY){
153 CommonTypes::putActorUniqueId($out, $object->actorUniqueId);
154 }else{
155 throw new \InvalidArgumentException("Unknown map object type $object->type");
156 }
157 }
158
159 VarInt::writeUnsignedInt($out, $decorationCount);
160 foreach($this->decorations as $decoration){
161 Byte::writeUnsigned($out, $decoration->getIcon());
162 Byte::writeUnsigned($out, $decoration->getRotation());
163 Byte::writeUnsigned($out, $decoration->getXOffset());
164 Byte::writeUnsigned($out, $decoration->getYOffset());
165 CommonTypes::putString($out, $decoration->getLabel());
166 VarInt::writeUnsignedInt($out, Binary::flipIntEndianness($decoration->getColor()->toRGBA()));
167 }
168 }
169
170 if($this->colors !== null){
171 VarInt::writeSignedInt($out, $this->colors->getWidth());
172 VarInt::writeSignedInt($out, $this->colors->getHeight());
173 VarInt::writeSignedInt($out, $this->xOffset);
174 VarInt::writeSignedInt($out, $this->yOffset);
175
176 VarInt::writeUnsignedInt($out, $this->colors->getWidth() * $this->colors->getHeight()); //list count, but we handle it as a 2D array... thanks for the confusion mojang
177
178 $this->colors->encode($out);
179 }
180 }
181
182 public function handle(PacketHandlerInterface $handler) : bool{
183 return $handler->handleClientboundMapItemData($this);
184 }
185}