PocketMine-MP 5.37.2 git-e507eb5e50da3ead3ae88ed2324df21e75820019
Loading...
Searching...
No Matches
PacketShapeData.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\types;
16
17use pmmp\encoding\Byte;
18use pmmp\encoding\ByteBufferReader;
19use pmmp\encoding\ByteBufferWriter;
20use pmmp\encoding\LE;
21use pmmp\encoding\VarInt;
27
31final class PacketShapeData{
32
33 public function __construct(
34 private int $networkId,
35 private ?ScriptDebugShapeType $type,
36 private ?Vector3 $location,
37 private ?float $scale,
38 private ?Vector3 $rotation,
39 private ?float $totalTimeLeft,
40 private ?Color $color,
41 private ?string $text,
42 private ?Vector3 $boxBound,
43 private ?Vector3 $lineEndLocation,
44 private ?float $arrowHeadLength,
45 private ?float $arrowHeadRadius,
46 private ?int $segments,
47 private int $dimensionId = DimensionIds::OVERWORLD,
48 ){}
49
50 public static function remove(int $networkId, int $dimensionId = DimensionIds::OVERWORLD) : self{
51 return new self($networkId, null, null, null, null, null, null, null, null, null, null, null, null, $dimensionId);
52 }
53
54 public static function line(int $networkId, Vector3 $location, Vector3 $lineEndLocation, ?Color $color = null, int $dimensionId = DimensionIds::OVERWORLD) : self{
55 return new self(
56 networkId: $networkId,
57 type: ScriptDebugShapeType::LINE,
58 location: $location,
59 scale: null,
60 rotation: null,
61 totalTimeLeft: null,
62 color: $color,
63 text: null,
64 boxBound: null,
65 lineEndLocation: $lineEndLocation,
66 arrowHeadLength: null,
67 arrowHeadRadius: null,
68 segments: null,
69 dimensionId: $dimensionId
70 );
71 }
72
73 public static function box(int $networkId, Vector3 $location, Vector3 $boxBound, ?float $scale = null, ?Color $color = null, int $dimensionId = DimensionIds::OVERWORLD) : self{
74 return new self(
75 networkId: $networkId,
76 type: ScriptDebugShapeType::BOX,
77 location: $location,
78 scale: $scale,
79 rotation: null,
80 totalTimeLeft: null,
81 color: $color,
82 text: null,
83 boxBound: $boxBound,
84 lineEndLocation: null,
85 arrowHeadLength: null,
86 arrowHeadRadius: null,
87 segments: null,
88 dimensionId: $dimensionId
89 );
90 }
91
92 public static function sphere(int $networkId, Vector3 $location, ?float $scale = null, ?Color $color = null, ?int $segments = null, int $dimensionId = DimensionIds::OVERWORLD) : self{
93 return new self(
94 networkId: $networkId,
95 type: ScriptDebugShapeType::SPHERE,
96 location: $location,
97 scale: $scale,
98 rotation: null,
99 totalTimeLeft: null,
100 color: $color,
101 text: null,
102 boxBound: null,
103 lineEndLocation: null,
104 arrowHeadLength: null,
105 arrowHeadRadius: null,
106 segments: $segments,
107 dimensionId: $dimensionId
108 );
109 }
110
111 public static function circle(int $networkId, Vector3 $location, ?float $scale = null, ?Color $color = null, ?int $segments = null, int $dimensionId = DimensionIds::OVERWORLD) : self{
112 return new self(
113 networkId: $networkId,
114 type: ScriptDebugShapeType::CIRCLE,
115 location: $location,
116 scale: $scale,
117 rotation: null,
118 totalTimeLeft: null,
119 color: $color,
120 text: null,
121 boxBound: null,
122 lineEndLocation: null,
123 arrowHeadLength: null,
124 arrowHeadRadius: null,
125 segments: $segments,
126 dimensionId: $dimensionId
127 );
128 }
129
130 public static function text(int $networkId, Vector3 $location, string $text, ?Color $color = null, int $dimensionId = DimensionIds::OVERWORLD) : self{
131 return new self(
132 networkId: $networkId,
133 type: ScriptDebugShapeType::TEXT,
134 location: $location,
135 scale: null,
136 rotation: null,
137 totalTimeLeft: null,
138 color: $color,
139 text: $text,
140 boxBound: null,
141 lineEndLocation: null,
142 arrowHeadLength: null,
143 arrowHeadRadius: null,
144 segments: null,
145 dimensionId: $dimensionId
146 );
147 }
148
149 public static function arrow(int $networkId, Vector3 $location, Vector3 $lineEndLocation, ?float $scale = null, ?Color $color = null, ?float $arrowHeadLength = null, ?float $arrowHeadRadius = null, ?int $segments = null, int $dimensionId = DimensionIds::OVERWORLD) : self{
150 return new self(
151 networkId: $networkId,
152 type: ScriptDebugShapeType::ARROW,
153 location: $location,
154 scale: $scale,
155 rotation: null,
156 totalTimeLeft: null,
157 color: $color,
158 text: null,
159 boxBound: null,
160 lineEndLocation: $lineEndLocation,
161 arrowHeadLength: $arrowHeadLength,
162 arrowHeadRadius: $arrowHeadRadius,
163 segments: $segments,
164 dimensionId: $dimensionId
165 );
166 }
167
168 public function getNetworkId() : int{ return $this->networkId; }
169
170 public function getType() : ?ScriptDebugShapeType{ return $this->type; }
171
172 public function getLocation() : ?Vector3{ return $this->location; }
173
174 public function getScale() : ?float{ return $this->scale; }
175
176 public function getRotation() : ?Vector3{ return $this->rotation; }
177
178 public function getTotalTimeLeft() : ?float{ return $this->totalTimeLeft; }
179
180 public function getColor() : ?Color{ return $this->color; }
181
182 public function getDimensionId() : int{ return $this->dimensionId; }
183
184 public function getText() : ?string{ return $this->text; }
185
186 public function getBoxBound() : ?Vector3{ return $this->boxBound; }
187
188 public function getLineEndLocation() : ?Vector3{ return $this->lineEndLocation; }
189
190 public function getArrowHeadLength() : ?float{ return $this->arrowHeadLength; }
191
192 public function getArrowHeadRadius() : ?float{ return $this->arrowHeadRadius; }
193
194 public function getSegments() : ?int{ return $this->segments; }
195
196 public static function read(ByteBufferReader $in) : self{
197 $networkId = VarInt::readUnsignedLong($in);
198 $shapeType = CommonTypes::readOptional($in, fn() => ScriptDebugShapeType::fromPacket(Byte::readUnsigned($in)));
199 $location = CommonTypes::readOptional($in, CommonTypes::getVector3(...));
200 $scale = CommonTypes::readOptional($in, LE::readFloat(...));
201 $rotation = CommonTypes::readOptional($in, CommonTypes::getVector3(...));
202 $totalTimeLeft = CommonTypes::readOptional($in, LE::readFloat(...));
203 $color = CommonTypes::readOptional($in, fn() => Color::fromARGB(LE::readUnsignedInt($in)));
204 $dimensionId = VarInt::readSignedInt($in);
205
206 $payloadType = VarInt::readUnsignedInt($in);
207 //WTF IS THIS HORROR SHOW
208 if(
209 ($shapeType !== null && $payloadType !== $shapeType->getPayloadType() && $payloadType !== ScriptDebugShapeType::PAYLOAD_TYPE_NONE) ||
210 ($shapeType === null && $payloadType !== ScriptDebugShapeType::PAYLOAD_TYPE_NONE)
211 ){
212 throw new PacketDecodeException("Unexpected payload type $payloadType for provided shape type " . ($shapeType->name ?? "(not set)"));
213 }
214 $text = null;
215 $boxBound = null;
216 $lineEndLocation = null;
217 $arrowHeadLength = null;
218 $arrowHeadRadius = null;
219 $segments = null;
220 switch($payloadType){
221 case ScriptDebugShapeType::PAYLOAD_TYPE_NONE:
222 break;
223 case ScriptDebugShapeType::PAYLOAD_TYPE_ARROW:
224 $lineEndLocation = CommonTypes::readOptional($in, CommonTypes::getVector3(...));
225 $arrowHeadLength = CommonTypes::readOptional($in, LE::readFloat(...));
226 $arrowHeadRadius = CommonTypes::readOptional($in, LE::readFloat(...));
227 $segments = CommonTypes::readOptional($in, Byte::readUnsigned(...));
228 break;
229 case ScriptDebugShapeType::PAYLOAD_TYPE_TEXT:
230 $text = CommonTypes::getString($in);
231 break;
232 case ScriptDebugShapeType::PAYLOAD_TYPE_BOX:
233 $boxBound = CommonTypes::getVector3($in);
234 break;
235 case ScriptDebugShapeType::PAYLOAD_TYPE_LINE:
236 $lineEndLocation = CommonTypes::getVector3($in);
237 break;
238 case ScriptDebugShapeType::PAYLOAD_TYPE_CIRCLE_OR_SPHERE:
239 $segments = Byte::readUnsigned($in);
240 break;
241 default:
242 throw new PacketDecodeException("Unexpected shape payload type $payloadType");
243 }
244
245 return new self(
246 $networkId,
247 $shapeType,
248 $location,
249 $scale,
250 $rotation,
251 $totalTimeLeft,
252 $color,
253 $text,
254 $boxBound,
255 $lineEndLocation,
256 $arrowHeadLength,
257 $arrowHeadRadius,
258 $segments,
259 $dimensionId
260 );
261 }
262
263 public function write(ByteBufferWriter $out) : void{
264 VarInt::writeUnsignedLong($out, $this->networkId);
265 CommonTypes::writeOptional($out, $this->type, fn(ByteBufferWriter $out, ScriptDebugShapeType $type) => Byte::writeUnsigned($out, $type->value));
266 CommonTypes::writeOptional($out, $this->location, CommonTypes::putVector3(...));
267 CommonTypes::writeOptional($out, $this->scale, LE::writeFloat(...));
268 CommonTypes::writeOptional($out, $this->rotation, CommonTypes::putVector3(...));
269 CommonTypes::writeOptional($out, $this->totalTimeLeft, LE::writeFloat(...));
270 CommonTypes::writeOptional($out, $this->color, fn(ByteBufferWriter $out, Color $color) => LE::writeUnsignedInt($out, $color->toARGB()));
271 VarInt::writeSignedInt($out, $this->dimensionId);
272
273 //A godawful hack for a godawful packet
274 $payloadType = $this->type?->getPayloadType() ?? ScriptDebugShapeType::PAYLOAD_TYPE_NONE;
275 if($this->type === null){
276 VarInt::writeUnsignedInt($out, ScriptDebugShapeType::PAYLOAD_TYPE_NONE);
277 }else{
278 switch($this->type){
279 case ScriptDebugShapeType::ARROW:
280 VarInt::writeUnsignedInt($out, $this->type->getPayloadType());
281 CommonTypes::writeOptional($out, $this->lineEndLocation, CommonTypes::putVector3(...));
282 CommonTypes::writeOptional($out, $this->arrowHeadLength, LE::writeFloat(...));
283 CommonTypes::writeOptional($out, $this->arrowHeadRadius, LE::writeFloat(...));
284 CommonTypes::writeOptional($out, $this->segments, Byte::writeUnsigned(...));
285 break;
286 case ScriptDebugShapeType::TEXT:
287 if($this->text !== null){
288 VarInt::writeUnsignedInt($out, $this->type->getPayloadType());
289 CommonTypes::putString($out, $this->text);
290 }else{
291 VarInt::writeUnsignedInt($out, ScriptDebugShapeType::PAYLOAD_TYPE_NONE);
292 }
293 break;
294 case ScriptDebugShapeType::BOX:
295 if($this->boxBound !== null){
296 VarInt::writeUnsignedInt($out, $this->type->getPayloadType());
297 CommonTypes::putVector3($out, $this->boxBound);
298 }else{
299 VarInt::writeUnsignedInt($out, ScriptDebugShapeType::PAYLOAD_TYPE_NONE);
300 }
301 break;
302 case ScriptDebugShapeType::LINE:
303 if($this->lineEndLocation !== null){
304 VarInt::writeUnsignedInt($out, $this->type->getPayloadType());
305 CommonTypes::putVector3($out, $this->lineEndLocation);
306 }else{
307 VarInt::writeUnsignedInt($out, ScriptDebugShapeType::PAYLOAD_TYPE_NONE);
308 }
309 break;
310 case ScriptDebugShapeType::CIRCLE:
311 case ScriptDebugShapeType::SPHERE:
312 if($this->segments !== null){
313 VarInt::writeUnsignedInt($out, $this->type->getPayloadType());
314 Byte::writeUnsigned($out, $this->segments);
315 }else{
316 VarInt::writeUnsignedInt($out, ScriptDebugShapeType::PAYLOAD_TYPE_NONE);
317 }
318 break;
319 default:
320 throw new \LogicException("Unknown payload type $payloadType");
321 }
322 }
323 }
324}